xref: /AOO41X/main/basegfx/source/polygon/b2dpolygon.cxx (revision 7925e91235a13cfa7fe14e5a7fcf556d16627bd6)
1cdf0e10cSrcweir /*************************************************************************
2cdf0e10cSrcweir  *
3cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4cdf0e10cSrcweir  *
5cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6cdf0e10cSrcweir  *
7cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8cdf0e10cSrcweir  *
9cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10cdf0e10cSrcweir  *
11cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14cdf0e10cSrcweir  *
15cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20cdf0e10cSrcweir  *
21cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25cdf0e10cSrcweir  *
26cdf0e10cSrcweir  ************************************************************************/
27cdf0e10cSrcweir 
28cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29cdf0e10cSrcweir #include "precompiled_basegfx.hxx"
30cdf0e10cSrcweir #include <osl/diagnose.h>
31cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygon.hxx>
32cdf0e10cSrcweir #include <basegfx/point/b2dpoint.hxx>
33cdf0e10cSrcweir #include <basegfx/vector/b2dvector.hxx>
34cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx>
35cdf0e10cSrcweir #include <basegfx/curve/b2dcubicbezier.hxx>
36cdf0e10cSrcweir #include <rtl/instance.hxx>
37cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx>
38cdf0e10cSrcweir #include <boost/scoped_ptr.hpp>
39cdf0e10cSrcweir #include <vector>
40cdf0e10cSrcweir #include <algorithm>
41cdf0e10cSrcweir 
42cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
43cdf0e10cSrcweir 
44cdf0e10cSrcweir struct CoordinateData2D : public basegfx::B2DPoint
45cdf0e10cSrcweir {
46cdf0e10cSrcweir public:
47cdf0e10cSrcweir     CoordinateData2D() {}
48cdf0e10cSrcweir 
49cdf0e10cSrcweir 	explicit CoordinateData2D(const basegfx::B2DPoint& rData)
50cdf0e10cSrcweir     :	B2DPoint(rData)
51cdf0e10cSrcweir 	{}
52cdf0e10cSrcweir 
53cdf0e10cSrcweir     CoordinateData2D& operator=(const basegfx::B2DPoint& rData)
54cdf0e10cSrcweir     {
55cdf0e10cSrcweir         B2DPoint::operator=(rData);
56cdf0e10cSrcweir         return *this;
57cdf0e10cSrcweir 	}
58cdf0e10cSrcweir 
59cdf0e10cSrcweir 	void transform(const basegfx::B2DHomMatrix& rMatrix)
60cdf0e10cSrcweir 	{
61cdf0e10cSrcweir         *this *= rMatrix;
62cdf0e10cSrcweir 	}
63cdf0e10cSrcweir };
64cdf0e10cSrcweir 
65cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
66cdf0e10cSrcweir 
67cdf0e10cSrcweir class CoordinateDataArray2D
68cdf0e10cSrcweir {
69cdf0e10cSrcweir 	typedef ::std::vector< CoordinateData2D > CoordinateData2DVector;
70cdf0e10cSrcweir 
71cdf0e10cSrcweir 	CoordinateData2DVector							maVector;
72cdf0e10cSrcweir 
73cdf0e10cSrcweir public:
74cdf0e10cSrcweir 	explicit CoordinateDataArray2D(sal_uInt32 nCount)
75cdf0e10cSrcweir 	:	maVector(nCount)
76cdf0e10cSrcweir 	{
77cdf0e10cSrcweir 	}
78cdf0e10cSrcweir 
79cdf0e10cSrcweir 	explicit CoordinateDataArray2D(const CoordinateDataArray2D& rOriginal)
80cdf0e10cSrcweir 	:	maVector(rOriginal.maVector)
81cdf0e10cSrcweir 	{
82cdf0e10cSrcweir 	}
83cdf0e10cSrcweir 
84cdf0e10cSrcweir 	CoordinateDataArray2D(const CoordinateDataArray2D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
85cdf0e10cSrcweir 	:	maVector(rOriginal.maVector.begin() + nIndex, rOriginal.maVector.begin() + (nIndex + nCount))
86cdf0e10cSrcweir 	{
87cdf0e10cSrcweir 	}
88cdf0e10cSrcweir 
89cdf0e10cSrcweir 	sal_uInt32 count() const
90cdf0e10cSrcweir 	{
91cdf0e10cSrcweir 		return maVector.size();
92cdf0e10cSrcweir 	}
93cdf0e10cSrcweir 
94cdf0e10cSrcweir 	bool operator==(const CoordinateDataArray2D& rCandidate) const
95cdf0e10cSrcweir 	{
96cdf0e10cSrcweir 		return (maVector == rCandidate.maVector);
97cdf0e10cSrcweir 	}
98cdf0e10cSrcweir 
99cdf0e10cSrcweir 	const basegfx::B2DPoint& getCoordinate(sal_uInt32 nIndex) const
100cdf0e10cSrcweir 	{
101cdf0e10cSrcweir         return maVector[nIndex];
102cdf0e10cSrcweir 	}
103cdf0e10cSrcweir 
104cdf0e10cSrcweir 	void setCoordinate(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue)
105cdf0e10cSrcweir 	{
106cdf0e10cSrcweir         maVector[nIndex] = rValue;
107cdf0e10cSrcweir 	}
108cdf0e10cSrcweir 
109cdf0e10cSrcweir 	void reserve(sal_uInt32 nCount)
110cdf0e10cSrcweir 	{
111cdf0e10cSrcweir 		maVector.reserve(nCount);
112cdf0e10cSrcweir 	}
113cdf0e10cSrcweir 
114cdf0e10cSrcweir 	void append(const CoordinateData2D& rValue)
115cdf0e10cSrcweir 	{
116cdf0e10cSrcweir 		maVector.push_back(rValue);
117cdf0e10cSrcweir 	}
118cdf0e10cSrcweir 
119cdf0e10cSrcweir 	void insert(sal_uInt32 nIndex, const CoordinateData2D& rValue, sal_uInt32 nCount)
120cdf0e10cSrcweir 	{
121cdf0e10cSrcweir 		if(nCount)
122cdf0e10cSrcweir 		{
123cdf0e10cSrcweir 			// add nCount copies of rValue
124cdf0e10cSrcweir 			CoordinateData2DVector::iterator aIndex(maVector.begin());
125cdf0e10cSrcweir 			aIndex += nIndex;
126cdf0e10cSrcweir 			maVector.insert(aIndex, nCount, rValue);
127cdf0e10cSrcweir 		}
128cdf0e10cSrcweir 	}
129cdf0e10cSrcweir 
130cdf0e10cSrcweir 	void insert(sal_uInt32 nIndex, const CoordinateDataArray2D& rSource)
131cdf0e10cSrcweir 	{
132cdf0e10cSrcweir 		const sal_uInt32 nCount(rSource.maVector.size());
133cdf0e10cSrcweir 
134cdf0e10cSrcweir 		if(nCount)
135cdf0e10cSrcweir 		{
136cdf0e10cSrcweir 			// insert data
137cdf0e10cSrcweir 			CoordinateData2DVector::iterator aIndex(maVector.begin());
138cdf0e10cSrcweir 			aIndex += nIndex;
139cdf0e10cSrcweir 			CoordinateData2DVector::const_iterator aStart(rSource.maVector.begin());
140cdf0e10cSrcweir 			CoordinateData2DVector::const_iterator aEnd(rSource.maVector.end());
141cdf0e10cSrcweir 			maVector.insert(aIndex, aStart, aEnd);
142cdf0e10cSrcweir 		}
143cdf0e10cSrcweir 	}
144cdf0e10cSrcweir 
145cdf0e10cSrcweir 	void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
146cdf0e10cSrcweir 	{
147cdf0e10cSrcweir 		if(nCount)
148cdf0e10cSrcweir 		{
149cdf0e10cSrcweir 			// remove point data
150cdf0e10cSrcweir 			CoordinateData2DVector::iterator aStart(maVector.begin());
151cdf0e10cSrcweir 			aStart += nIndex;
152cdf0e10cSrcweir 			const CoordinateData2DVector::iterator aEnd(aStart + nCount);
153cdf0e10cSrcweir 			maVector.erase(aStart, aEnd);
154cdf0e10cSrcweir 		}
155cdf0e10cSrcweir 	}
156cdf0e10cSrcweir 
157cdf0e10cSrcweir 	void flip(bool bIsClosed)
158cdf0e10cSrcweir 	{
159cdf0e10cSrcweir 		if(maVector.size() > 1)
160cdf0e10cSrcweir 		{
161cdf0e10cSrcweir 			// to keep the same point at index 0, just flip all points except the
162cdf0e10cSrcweir 			// first one when closed
163cdf0e10cSrcweir 			const sal_uInt32 nHalfSize(bIsClosed ? (maVector.size() - 1) >> 1 : maVector.size() >> 1);
164cdf0e10cSrcweir 			CoordinateData2DVector::iterator aStart(bIsClosed ? maVector.begin() + 1 : maVector.begin());
165cdf0e10cSrcweir 			CoordinateData2DVector::iterator aEnd(maVector.end() - 1);
166cdf0e10cSrcweir 
167cdf0e10cSrcweir 			for(sal_uInt32 a(0); a < nHalfSize; a++)
168cdf0e10cSrcweir 			{
169cdf0e10cSrcweir 				::std::swap(*aStart, *aEnd);
170cdf0e10cSrcweir 				aStart++;
171cdf0e10cSrcweir 				aEnd--;
172cdf0e10cSrcweir 			}
173cdf0e10cSrcweir 		}
174cdf0e10cSrcweir 	}
175cdf0e10cSrcweir 
176cdf0e10cSrcweir 	void removeDoublePointsAtBeginEnd()
177cdf0e10cSrcweir 	{
178cdf0e10cSrcweir 		// remove from end as long as there are at least two points
179cdf0e10cSrcweir 		// and begin/end are equal
180cdf0e10cSrcweir 		while((maVector.size() > 1) && (maVector[0] == maVector[maVector.size() - 1]))
181cdf0e10cSrcweir 		{
182cdf0e10cSrcweir 			maVector.pop_back();
183cdf0e10cSrcweir 		}
184cdf0e10cSrcweir 	}
185cdf0e10cSrcweir 
186cdf0e10cSrcweir 	void removeDoublePointsWholeTrack()
187cdf0e10cSrcweir 	{
188cdf0e10cSrcweir 		sal_uInt32 nIndex(0);
189cdf0e10cSrcweir 
190cdf0e10cSrcweir 		// test as long as there are at least two points and as long as the index
191cdf0e10cSrcweir 		// is smaller or equal second last point
192cdf0e10cSrcweir 		while((maVector.size() > 1) && (nIndex <= maVector.size() - 2))
193cdf0e10cSrcweir 		{
194cdf0e10cSrcweir 			if(maVector[nIndex] == maVector[nIndex + 1])
195cdf0e10cSrcweir 			{
196cdf0e10cSrcweir 				// if next is same as index, delete next
197cdf0e10cSrcweir 				maVector.erase(maVector.begin() + (nIndex + 1));
198cdf0e10cSrcweir 			}
199cdf0e10cSrcweir 			else
200cdf0e10cSrcweir 			{
201cdf0e10cSrcweir 				// if different, step forward
202cdf0e10cSrcweir 				nIndex++;
203cdf0e10cSrcweir 			}
204cdf0e10cSrcweir 		}
205cdf0e10cSrcweir 	}
206cdf0e10cSrcweir 
207cdf0e10cSrcweir 	void transform(const basegfx::B2DHomMatrix& rMatrix)
208cdf0e10cSrcweir 	{
209cdf0e10cSrcweir 		CoordinateData2DVector::iterator aStart(maVector.begin());
210cdf0e10cSrcweir 		CoordinateData2DVector::iterator aEnd(maVector.end());
211cdf0e10cSrcweir 
212cdf0e10cSrcweir 		for(; aStart != aEnd; aStart++)
213cdf0e10cSrcweir 		{
214cdf0e10cSrcweir 			aStart->transform(rMatrix);
215cdf0e10cSrcweir 		}
216cdf0e10cSrcweir 	}
217cdf0e10cSrcweir 
218cdf0e10cSrcweir     const basegfx::B2DPoint* begin() const
219cdf0e10cSrcweir     {
220cdf0e10cSrcweir         if(maVector.empty())
221cdf0e10cSrcweir             return 0;
222cdf0e10cSrcweir         else
223cdf0e10cSrcweir             return &maVector.front();
224cdf0e10cSrcweir     }
225cdf0e10cSrcweir 
226cdf0e10cSrcweir     const basegfx::B2DPoint* end() const
227cdf0e10cSrcweir     {
228cdf0e10cSrcweir         if(maVector.empty())
229cdf0e10cSrcweir             return 0;
230cdf0e10cSrcweir         else
231cdf0e10cSrcweir             return (&maVector.back())+1;
232cdf0e10cSrcweir     }
233cdf0e10cSrcweir 
234cdf0e10cSrcweir     basegfx::B2DPoint* begin()
235cdf0e10cSrcweir     {
236cdf0e10cSrcweir         if(maVector.empty())
237cdf0e10cSrcweir             return 0;
238cdf0e10cSrcweir         else
239cdf0e10cSrcweir             return &maVector.front();
240cdf0e10cSrcweir     }
241cdf0e10cSrcweir 
242cdf0e10cSrcweir     basegfx::B2DPoint* end()
243cdf0e10cSrcweir     {
244cdf0e10cSrcweir         if(maVector.empty())
245cdf0e10cSrcweir             return 0;
246cdf0e10cSrcweir         else
247cdf0e10cSrcweir             return (&maVector.back())+1;
248cdf0e10cSrcweir     }
249cdf0e10cSrcweir };
250cdf0e10cSrcweir 
251cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
252cdf0e10cSrcweir 
253cdf0e10cSrcweir class ControlVectorPair2D
254cdf0e10cSrcweir {
255cdf0e10cSrcweir 	basegfx::B2DVector							maPrevVector;
256cdf0e10cSrcweir 	basegfx::B2DVector							maNextVector;
257cdf0e10cSrcweir 
258cdf0e10cSrcweir public:
259*7925e912SMichael Stahl     explicit ControlVectorPair2D () { }
260*7925e912SMichael Stahl 
261cdf0e10cSrcweir 	const basegfx::B2DVector& getPrevVector() const
262cdf0e10cSrcweir 	{
263cdf0e10cSrcweir 		return maPrevVector;
264cdf0e10cSrcweir 	}
265cdf0e10cSrcweir 
266cdf0e10cSrcweir 	void setPrevVector(const basegfx::B2DVector& rValue)
267cdf0e10cSrcweir 	{
268cdf0e10cSrcweir 		if(rValue != maPrevVector)
269cdf0e10cSrcweir 			maPrevVector = rValue;
270cdf0e10cSrcweir 	}
271cdf0e10cSrcweir 
272cdf0e10cSrcweir 	const basegfx::B2DVector& getNextVector() const
273cdf0e10cSrcweir 	{
274cdf0e10cSrcweir 		return maNextVector;
275cdf0e10cSrcweir 	}
276cdf0e10cSrcweir 
277cdf0e10cSrcweir 	void setNextVector(const basegfx::B2DVector& rValue)
278cdf0e10cSrcweir 	{
279cdf0e10cSrcweir 		if(rValue != maNextVector)
280cdf0e10cSrcweir 			maNextVector = rValue;
281cdf0e10cSrcweir 	}
282cdf0e10cSrcweir 
283cdf0e10cSrcweir 	bool operator==(const ControlVectorPair2D& rData) const
284cdf0e10cSrcweir 	{
285cdf0e10cSrcweir 		return (maPrevVector == rData.getPrevVector() && maNextVector == rData.getNextVector());
286cdf0e10cSrcweir 	}
287cdf0e10cSrcweir 
288cdf0e10cSrcweir 	void flip()
289cdf0e10cSrcweir 	{
290cdf0e10cSrcweir 		::std::swap(maPrevVector, maNextVector);
291cdf0e10cSrcweir 	}
292cdf0e10cSrcweir };
293cdf0e10cSrcweir 
294cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
295cdf0e10cSrcweir 
296cdf0e10cSrcweir class ControlVectorArray2D
297cdf0e10cSrcweir {
298cdf0e10cSrcweir 	typedef ::std::vector< ControlVectorPair2D > ControlVectorPair2DVector;
299cdf0e10cSrcweir 
300cdf0e10cSrcweir 	ControlVectorPair2DVector							maVector;
301cdf0e10cSrcweir 	sal_uInt32											mnUsedVectors;
302cdf0e10cSrcweir 
303cdf0e10cSrcweir public:
304cdf0e10cSrcweir 	explicit ControlVectorArray2D(sal_uInt32 nCount)
305cdf0e10cSrcweir 	:	maVector(nCount),
306cdf0e10cSrcweir 		mnUsedVectors(0)
307cdf0e10cSrcweir 	{}
308cdf0e10cSrcweir 
309cdf0e10cSrcweir 	ControlVectorArray2D(const ControlVectorArray2D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
310cdf0e10cSrcweir 	:	maVector(),
311cdf0e10cSrcweir 		mnUsedVectors(0)
312cdf0e10cSrcweir 	{
313cdf0e10cSrcweir 		ControlVectorPair2DVector::const_iterator aStart(rOriginal.maVector.begin());
314cdf0e10cSrcweir 		aStart += nIndex;
315cdf0e10cSrcweir 		ControlVectorPair2DVector::const_iterator aEnd(aStart);
316cdf0e10cSrcweir 		aEnd += nCount;
317cdf0e10cSrcweir 		maVector.reserve(nCount);
318cdf0e10cSrcweir 
319cdf0e10cSrcweir 		for(; aStart != aEnd; aStart++)
320cdf0e10cSrcweir 		{
321cdf0e10cSrcweir 			if(!aStart->getPrevVector().equalZero())
322cdf0e10cSrcweir 				mnUsedVectors++;
323cdf0e10cSrcweir 
324cdf0e10cSrcweir 			if(!aStart->getNextVector().equalZero())
325cdf0e10cSrcweir 				mnUsedVectors++;
326cdf0e10cSrcweir 
327cdf0e10cSrcweir 			maVector.push_back(*aStart);
328cdf0e10cSrcweir 		}
329cdf0e10cSrcweir 	}
330cdf0e10cSrcweir 
331cdf0e10cSrcweir 	sal_uInt32 count() const
332cdf0e10cSrcweir 	{
333cdf0e10cSrcweir 		return maVector.size();
334cdf0e10cSrcweir 	}
335cdf0e10cSrcweir 
336cdf0e10cSrcweir 	bool operator==(const ControlVectorArray2D& rCandidate) const
337cdf0e10cSrcweir 	{
338cdf0e10cSrcweir 		return (maVector == rCandidate.maVector);
339cdf0e10cSrcweir 	}
340cdf0e10cSrcweir 
341cdf0e10cSrcweir 	bool isUsed() const
342cdf0e10cSrcweir 	{
343cdf0e10cSrcweir 		return (0 != mnUsedVectors);
344cdf0e10cSrcweir 	}
345cdf0e10cSrcweir 
346cdf0e10cSrcweir 	const basegfx::B2DVector& getPrevVector(sal_uInt32 nIndex) const
347cdf0e10cSrcweir 	{
348cdf0e10cSrcweir 		return maVector[nIndex].getPrevVector();
349cdf0e10cSrcweir 	}
350cdf0e10cSrcweir 
351cdf0e10cSrcweir 	void setPrevVector(sal_uInt32 nIndex, const basegfx::B2DVector& rValue)
352cdf0e10cSrcweir 	{
353cdf0e10cSrcweir 		bool bWasUsed(mnUsedVectors && !maVector[nIndex].getPrevVector().equalZero());
354cdf0e10cSrcweir 		bool bIsUsed(!rValue.equalZero());
355cdf0e10cSrcweir 
356cdf0e10cSrcweir 		if(bWasUsed)
357cdf0e10cSrcweir 		{
358cdf0e10cSrcweir 			if(bIsUsed)
359cdf0e10cSrcweir 			{
360cdf0e10cSrcweir 				maVector[nIndex].setPrevVector(rValue);
361cdf0e10cSrcweir 			}
362cdf0e10cSrcweir 			else
363cdf0e10cSrcweir 			{
364cdf0e10cSrcweir 				maVector[nIndex].setPrevVector(basegfx::B2DVector::getEmptyVector());
365cdf0e10cSrcweir 				mnUsedVectors--;
366cdf0e10cSrcweir 			}
367cdf0e10cSrcweir 		}
368cdf0e10cSrcweir 		else
369cdf0e10cSrcweir 		{
370cdf0e10cSrcweir 			if(bIsUsed)
371cdf0e10cSrcweir 			{
372cdf0e10cSrcweir 				maVector[nIndex].setPrevVector(rValue);
373cdf0e10cSrcweir 				mnUsedVectors++;
374cdf0e10cSrcweir 			}
375cdf0e10cSrcweir 		}
376cdf0e10cSrcweir 	}
377cdf0e10cSrcweir 
378cdf0e10cSrcweir 	const basegfx::B2DVector& getNextVector(sal_uInt32 nIndex) const
379cdf0e10cSrcweir 	{
380cdf0e10cSrcweir 		return maVector[nIndex].getNextVector();
381cdf0e10cSrcweir 	}
382cdf0e10cSrcweir 
383cdf0e10cSrcweir 	void setNextVector(sal_uInt32 nIndex, const basegfx::B2DVector& rValue)
384cdf0e10cSrcweir 	{
385cdf0e10cSrcweir 		bool bWasUsed(mnUsedVectors && !maVector[nIndex].getNextVector().equalZero());
386cdf0e10cSrcweir 		bool bIsUsed(!rValue.equalZero());
387cdf0e10cSrcweir 
388cdf0e10cSrcweir 		if(bWasUsed)
389cdf0e10cSrcweir 		{
390cdf0e10cSrcweir 			if(bIsUsed)
391cdf0e10cSrcweir 			{
392cdf0e10cSrcweir 				maVector[nIndex].setNextVector(rValue);
393cdf0e10cSrcweir 			}
394cdf0e10cSrcweir 			else
395cdf0e10cSrcweir 			{
396cdf0e10cSrcweir 				maVector[nIndex].setNextVector(basegfx::B2DVector::getEmptyVector());
397cdf0e10cSrcweir 				mnUsedVectors--;
398cdf0e10cSrcweir 			}
399cdf0e10cSrcweir 		}
400cdf0e10cSrcweir 		else
401cdf0e10cSrcweir 		{
402cdf0e10cSrcweir 			if(bIsUsed)
403cdf0e10cSrcweir 			{
404cdf0e10cSrcweir 				maVector[nIndex].setNextVector(rValue);
405cdf0e10cSrcweir 				mnUsedVectors++;
406cdf0e10cSrcweir 			}
407cdf0e10cSrcweir 		}
408cdf0e10cSrcweir 	}
409cdf0e10cSrcweir 
410cdf0e10cSrcweir 	void append(const ControlVectorPair2D& rValue)
411cdf0e10cSrcweir 	{
412cdf0e10cSrcweir 		maVector.push_back(rValue);
413cdf0e10cSrcweir 
414cdf0e10cSrcweir 		if(!rValue.getPrevVector().equalZero())
415cdf0e10cSrcweir 			mnUsedVectors += 1;
416cdf0e10cSrcweir 
417cdf0e10cSrcweir 		if(!rValue.getNextVector().equalZero())
418cdf0e10cSrcweir 			mnUsedVectors += 1;
419cdf0e10cSrcweir 	}
420cdf0e10cSrcweir 
421cdf0e10cSrcweir 	void insert(sal_uInt32 nIndex, const ControlVectorPair2D& rValue, sal_uInt32 nCount)
422cdf0e10cSrcweir 	{
423cdf0e10cSrcweir 		if(nCount)
424cdf0e10cSrcweir 		{
425cdf0e10cSrcweir 			// add nCount copies of rValue
426cdf0e10cSrcweir 			ControlVectorPair2DVector::iterator aIndex(maVector.begin());
427cdf0e10cSrcweir 			aIndex += nIndex;
428cdf0e10cSrcweir 			maVector.insert(aIndex, nCount, rValue);
429cdf0e10cSrcweir 
430cdf0e10cSrcweir 			if(!rValue.getPrevVector().equalZero())
431cdf0e10cSrcweir 				mnUsedVectors += nCount;
432cdf0e10cSrcweir 
433cdf0e10cSrcweir 			if(!rValue.getNextVector().equalZero())
434cdf0e10cSrcweir 				mnUsedVectors += nCount;
435cdf0e10cSrcweir 		}
436cdf0e10cSrcweir 	}
437cdf0e10cSrcweir 
438cdf0e10cSrcweir 	void insert(sal_uInt32 nIndex, const ControlVectorArray2D& rSource)
439cdf0e10cSrcweir 	{
440cdf0e10cSrcweir 		const sal_uInt32 nCount(rSource.maVector.size());
441cdf0e10cSrcweir 
442cdf0e10cSrcweir 		if(nCount)
443cdf0e10cSrcweir 		{
444cdf0e10cSrcweir 			// insert data
445cdf0e10cSrcweir 			ControlVectorPair2DVector::iterator aIndex(maVector.begin());
446cdf0e10cSrcweir 			aIndex += nIndex;
447cdf0e10cSrcweir 			ControlVectorPair2DVector::const_iterator aStart(rSource.maVector.begin());
448cdf0e10cSrcweir 			ControlVectorPair2DVector::const_iterator aEnd(rSource.maVector.end());
449cdf0e10cSrcweir 			maVector.insert(aIndex, aStart, aEnd);
450cdf0e10cSrcweir 
451cdf0e10cSrcweir 			for(; aStart != aEnd; aStart++)
452cdf0e10cSrcweir 			{
453cdf0e10cSrcweir 				if(!aStart->getPrevVector().equalZero())
454cdf0e10cSrcweir 					mnUsedVectors++;
455cdf0e10cSrcweir 
456cdf0e10cSrcweir 				if(!aStart->getNextVector().equalZero())
457cdf0e10cSrcweir 					mnUsedVectors++;
458cdf0e10cSrcweir 			}
459cdf0e10cSrcweir 		}
460cdf0e10cSrcweir 	}
461cdf0e10cSrcweir 
462cdf0e10cSrcweir 	void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
463cdf0e10cSrcweir 	{
464cdf0e10cSrcweir 		if(nCount)
465cdf0e10cSrcweir 		{
466cdf0e10cSrcweir 			const ControlVectorPair2DVector::iterator aDeleteStart(maVector.begin() + nIndex);
467cdf0e10cSrcweir 			const ControlVectorPair2DVector::iterator aDeleteEnd(aDeleteStart + nCount);
468cdf0e10cSrcweir 			ControlVectorPair2DVector::const_iterator aStart(aDeleteStart);
469cdf0e10cSrcweir 
470cdf0e10cSrcweir 			for(; mnUsedVectors && aStart != aDeleteEnd; aStart++)
471cdf0e10cSrcweir 			{
472cdf0e10cSrcweir 				if(!aStart->getPrevVector().equalZero())
473cdf0e10cSrcweir 					mnUsedVectors--;
474cdf0e10cSrcweir 
475cdf0e10cSrcweir 				if(mnUsedVectors && !aStart->getNextVector().equalZero())
476cdf0e10cSrcweir 					mnUsedVectors--;
477cdf0e10cSrcweir 			}
478cdf0e10cSrcweir 
479cdf0e10cSrcweir 			// remove point data
480cdf0e10cSrcweir 			maVector.erase(aDeleteStart, aDeleteEnd);
481cdf0e10cSrcweir 		}
482cdf0e10cSrcweir 	}
483cdf0e10cSrcweir 
484cdf0e10cSrcweir 	void flip(bool bIsClosed)
485cdf0e10cSrcweir 	{
486cdf0e10cSrcweir 		if(maVector.size() > 1)
487cdf0e10cSrcweir 		{
488cdf0e10cSrcweir 			// to keep the same point at index 0, just flip all points except the
489cdf0e10cSrcweir 			// first one when closed
490cdf0e10cSrcweir 			const sal_uInt32 nHalfSize(bIsClosed ? (maVector.size() - 1) >> 1 : maVector.size() >> 1);
491cdf0e10cSrcweir 			ControlVectorPair2DVector::iterator aStart(bIsClosed ? maVector.begin() + 1 : maVector.begin());
492cdf0e10cSrcweir 			ControlVectorPair2DVector::iterator aEnd(maVector.end() - 1);
493cdf0e10cSrcweir 
494cdf0e10cSrcweir 			for(sal_uInt32 a(0); a < nHalfSize; a++)
495cdf0e10cSrcweir 			{
496cdf0e10cSrcweir 				// swap Prev and Next
497cdf0e10cSrcweir 				aStart->flip();
498cdf0e10cSrcweir 				aEnd->flip();
499cdf0e10cSrcweir 
500cdf0e10cSrcweir 				// swap entries
501cdf0e10cSrcweir 				::std::swap(*aStart, *aEnd);
502cdf0e10cSrcweir 
503cdf0e10cSrcweir 				aStart++;
504cdf0e10cSrcweir 				aEnd--;
505cdf0e10cSrcweir 			}
506cdf0e10cSrcweir 
507cdf0e10cSrcweir 			if(aStart == aEnd)
508cdf0e10cSrcweir 			{
509cdf0e10cSrcweir 				// swap Prev and Next at middle element (if exists)
510cdf0e10cSrcweir 				aStart->flip();
511cdf0e10cSrcweir 			}
512cdf0e10cSrcweir 
513cdf0e10cSrcweir 			if(bIsClosed)
514cdf0e10cSrcweir 			{
515cdf0e10cSrcweir 				// swap Prev and Next at start element
516cdf0e10cSrcweir 				maVector.begin()->flip();
517cdf0e10cSrcweir 			}
518cdf0e10cSrcweir 		}
519cdf0e10cSrcweir 	}
520cdf0e10cSrcweir };
521cdf0e10cSrcweir 
522cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
523cdf0e10cSrcweir 
524cdf0e10cSrcweir class ImplBufferedData
525cdf0e10cSrcweir {
526cdf0e10cSrcweir private:
527cdf0e10cSrcweir 	// Possibility to hold the last subdivision
528cdf0e10cSrcweir 	boost::scoped_ptr< basegfx::B2DPolygon >		mpDefaultSubdivision;
529cdf0e10cSrcweir 
530cdf0e10cSrcweir     // Possibility to hold the last B2DRange calculation
531cdf0e10cSrcweir 	boost::scoped_ptr< basegfx::B2DRange >		    mpB2DRange;
532cdf0e10cSrcweir 
533cdf0e10cSrcweir public:
534cdf0e10cSrcweir     ImplBufferedData()
535cdf0e10cSrcweir     :   mpDefaultSubdivision(),
536cdf0e10cSrcweir         mpB2DRange()
537cdf0e10cSrcweir     {}
538cdf0e10cSrcweir 
539cdf0e10cSrcweir     const basegfx::B2DPolygon& getDefaultAdaptiveSubdivision(const basegfx::B2DPolygon& rSource) const
540cdf0e10cSrcweir 	{
541cdf0e10cSrcweir 		if(!mpDefaultSubdivision)
542cdf0e10cSrcweir 		{
543cdf0e10cSrcweir 			const_cast< ImplBufferedData* >(this)->mpDefaultSubdivision.reset(new basegfx::B2DPolygon(basegfx::tools::adaptiveSubdivideByCount(rSource, 9)));
544cdf0e10cSrcweir 		}
545cdf0e10cSrcweir 
546cdf0e10cSrcweir         return *mpDefaultSubdivision;
547cdf0e10cSrcweir 	}
548cdf0e10cSrcweir 
549cdf0e10cSrcweir     const basegfx::B2DRange& getB2DRange(const basegfx::B2DPolygon& rSource) const
550cdf0e10cSrcweir     {
551cdf0e10cSrcweir 		if(!mpB2DRange)
552cdf0e10cSrcweir 		{
553cdf0e10cSrcweir 			basegfx::B2DRange aNewRange;
554cdf0e10cSrcweir 			const sal_uInt32 nPointCount(rSource.count());
555cdf0e10cSrcweir 
556cdf0e10cSrcweir 			if(nPointCount)
557cdf0e10cSrcweir 			{
558cdf0e10cSrcweir 				for(sal_uInt32 a(0); a < nPointCount; a++)
559cdf0e10cSrcweir 				{
560cdf0e10cSrcweir 					aNewRange.expand(rSource.getB2DPoint(a));
561cdf0e10cSrcweir 				}
562cdf0e10cSrcweir 
563cdf0e10cSrcweir 				if(rSource.areControlPointsUsed())
564cdf0e10cSrcweir 				{
565cdf0e10cSrcweir 					const sal_uInt32 nEdgeCount(rSource.isClosed() ? nPointCount : nPointCount - 1);
566cdf0e10cSrcweir 
567cdf0e10cSrcweir 					if(nEdgeCount)
568cdf0e10cSrcweir 					{
569cdf0e10cSrcweir 						basegfx::B2DCubicBezier aEdge;
570cdf0e10cSrcweir 						aEdge.setStartPoint(rSource.getB2DPoint(0));
571cdf0e10cSrcweir 
572cdf0e10cSrcweir 						for(sal_uInt32 b(0); b < nEdgeCount; b++)
573cdf0e10cSrcweir 						{
574cdf0e10cSrcweir 							const sal_uInt32 nNextIndex((b + 1) % nPointCount);
575cdf0e10cSrcweir 							aEdge.setControlPointA(rSource.getNextControlPoint(b));
576cdf0e10cSrcweir 							aEdge.setControlPointB(rSource.getPrevControlPoint(nNextIndex));
577cdf0e10cSrcweir 							aEdge.setEndPoint(rSource.getB2DPoint(nNextIndex));
578cdf0e10cSrcweir 
579cdf0e10cSrcweir 							if(aEdge.isBezier())
580cdf0e10cSrcweir 							{
581cdf0e10cSrcweir 								const basegfx::B2DRange aBezierRangeWithControlPoints(aEdge.getRange());
582cdf0e10cSrcweir 
583cdf0e10cSrcweir 								if(!aNewRange.isInside(aBezierRangeWithControlPoints))
584cdf0e10cSrcweir 								{
585cdf0e10cSrcweir 									// the range with control points of the current edge is not completely
586cdf0e10cSrcweir 									// inside the current range without control points. Expand current range by
587cdf0e10cSrcweir 									// subdividing the bezier segment.
588cdf0e10cSrcweir 									// Ideal here is a subdivision at the extreme values, so use
589cdf0e10cSrcweir 									// getAllExtremumPositions to get all extremas in one run
590cdf0e10cSrcweir 									::std::vector< double > aExtremas;
591cdf0e10cSrcweir 
592cdf0e10cSrcweir 									aExtremas.reserve(4);
593cdf0e10cSrcweir 									aEdge.getAllExtremumPositions(aExtremas);
594cdf0e10cSrcweir 
595cdf0e10cSrcweir 									const sal_uInt32 nExtremaCount(aExtremas.size());
596cdf0e10cSrcweir 
597cdf0e10cSrcweir 									for(sal_uInt32 c(0); c < nExtremaCount; c++)
598cdf0e10cSrcweir 									{
599cdf0e10cSrcweir 										aNewRange.expand(aEdge.interpolatePoint(aExtremas[c]));
600cdf0e10cSrcweir 									}
601cdf0e10cSrcweir 								}
602cdf0e10cSrcweir 							}
603cdf0e10cSrcweir 
604cdf0e10cSrcweir 							// prepare next edge
605cdf0e10cSrcweir 							aEdge.setStartPoint(aEdge.getEndPoint());
606cdf0e10cSrcweir 						}
607cdf0e10cSrcweir 					}
608cdf0e10cSrcweir 				}
609cdf0e10cSrcweir 			}
610cdf0e10cSrcweir 
611cdf0e10cSrcweir 			const_cast< ImplBufferedData* >(this)->mpB2DRange.reset(new basegfx::B2DRange(aNewRange));
612cdf0e10cSrcweir 		}
613cdf0e10cSrcweir 
614cdf0e10cSrcweir         return *mpB2DRange;
615cdf0e10cSrcweir     }
616cdf0e10cSrcweir };
617cdf0e10cSrcweir 
618cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
619cdf0e10cSrcweir 
620cdf0e10cSrcweir class ImplB2DPolygon
621cdf0e10cSrcweir {
622cdf0e10cSrcweir private:
623cdf0e10cSrcweir 	// The point vector. This vector exists always and defines the
624cdf0e10cSrcweir 	// count of members.
625cdf0e10cSrcweir 	CoordinateDataArray2D							maPoints;
626cdf0e10cSrcweir 
627cdf0e10cSrcweir 	// The control point vectors. This vectors are created on demand
628cdf0e10cSrcweir 	// and may be zero.
629cdf0e10cSrcweir 	boost::scoped_ptr< ControlVectorArray2D >		mpControlVector;
630cdf0e10cSrcweir 
631cdf0e10cSrcweir     // buffered data for e.g. default subdivision and range
632cdf0e10cSrcweir     boost::scoped_ptr< ImplBufferedData >           mpBufferedData;
633cdf0e10cSrcweir 
634cdf0e10cSrcweir 	// flag which decides if this polygon is opened or closed
635cdf0e10cSrcweir 	bool                                            mbIsClosed;
636cdf0e10cSrcweir 
637cdf0e10cSrcweir public:
638cdf0e10cSrcweir 	const basegfx::B2DPolygon& getDefaultAdaptiveSubdivision(const basegfx::B2DPolygon& rSource) const
639cdf0e10cSrcweir 	{
640cdf0e10cSrcweir 		if(!mpControlVector || !mpControlVector->isUsed())
641cdf0e10cSrcweir         {
642cdf0e10cSrcweir     		return rSource;
643cdf0e10cSrcweir         }
644cdf0e10cSrcweir 
645cdf0e10cSrcweir         if(!mpBufferedData)
646cdf0e10cSrcweir         {
647cdf0e10cSrcweir 			const_cast< ImplB2DPolygon* >(this)->mpBufferedData.reset(new ImplBufferedData);
648cdf0e10cSrcweir         }
649cdf0e10cSrcweir 
650cdf0e10cSrcweir         return mpBufferedData->getDefaultAdaptiveSubdivision(rSource);
651cdf0e10cSrcweir 	}
652cdf0e10cSrcweir 
653cdf0e10cSrcweir 	const basegfx::B2DRange& getB2DRange(const basegfx::B2DPolygon& rSource) const
654cdf0e10cSrcweir     {
655cdf0e10cSrcweir         if(!mpBufferedData)
656cdf0e10cSrcweir         {
657cdf0e10cSrcweir 			const_cast< ImplB2DPolygon* >(this)->mpBufferedData.reset(new ImplBufferedData);
658cdf0e10cSrcweir         }
659cdf0e10cSrcweir 
660cdf0e10cSrcweir         return mpBufferedData->getB2DRange(rSource);
661cdf0e10cSrcweir     }
662cdf0e10cSrcweir 
663cdf0e10cSrcweir 	ImplB2DPolygon()
664cdf0e10cSrcweir 	:	maPoints(0),
665cdf0e10cSrcweir 		mpControlVector(),
666cdf0e10cSrcweir 		mpBufferedData(),
667cdf0e10cSrcweir         mbIsClosed(false)
668cdf0e10cSrcweir 	{}
669cdf0e10cSrcweir 
670cdf0e10cSrcweir 	ImplB2DPolygon(const ImplB2DPolygon& rToBeCopied)
671cdf0e10cSrcweir 	:	maPoints(rToBeCopied.maPoints),
672cdf0e10cSrcweir 		mpControlVector(),
673cdf0e10cSrcweir 		mpBufferedData(),
674cdf0e10cSrcweir 		mbIsClosed(rToBeCopied.mbIsClosed)
675cdf0e10cSrcweir 	{
676cdf0e10cSrcweir 		// complete initialization using copy
677cdf0e10cSrcweir 		if(rToBeCopied.mpControlVector && rToBeCopied.mpControlVector->isUsed())
678cdf0e10cSrcweir         {
679cdf0e10cSrcweir 			mpControlVector.reset( new ControlVectorArray2D(*rToBeCopied.mpControlVector) );
680cdf0e10cSrcweir         }
681cdf0e10cSrcweir 	}
682cdf0e10cSrcweir 
683cdf0e10cSrcweir 	ImplB2DPolygon(const ImplB2DPolygon& rToBeCopied, sal_uInt32 nIndex, sal_uInt32 nCount)
684cdf0e10cSrcweir 	:	maPoints(rToBeCopied.maPoints, nIndex, nCount),
685cdf0e10cSrcweir 		mpControlVector(),
686cdf0e10cSrcweir 		mpBufferedData(),
687cdf0e10cSrcweir 		mbIsClosed(rToBeCopied.mbIsClosed)
688cdf0e10cSrcweir 	{
689cdf0e10cSrcweir 		// complete initialization using partly copy
690cdf0e10cSrcweir 		if(rToBeCopied.mpControlVector && rToBeCopied.mpControlVector->isUsed())
691cdf0e10cSrcweir 		{
692cdf0e10cSrcweir 			mpControlVector.reset( new ControlVectorArray2D(*rToBeCopied.mpControlVector, nIndex, nCount) );
693cdf0e10cSrcweir 
694cdf0e10cSrcweir 			if(!mpControlVector->isUsed())
695cdf0e10cSrcweir                 mpControlVector.reset();
696cdf0e10cSrcweir 		}
697cdf0e10cSrcweir 	}
698cdf0e10cSrcweir 
699cdf0e10cSrcweir     ImplB2DPolygon& operator=( const ImplB2DPolygon& rToBeCopied )
700cdf0e10cSrcweir     {
701cdf0e10cSrcweir 		maPoints = rToBeCopied.maPoints;
702cdf0e10cSrcweir 		mpControlVector.reset();
703cdf0e10cSrcweir 		mpBufferedData.reset();
704cdf0e10cSrcweir 		mbIsClosed = rToBeCopied.mbIsClosed;
705cdf0e10cSrcweir 
706cdf0e10cSrcweir 		// complete initialization using copy
707cdf0e10cSrcweir 		if(rToBeCopied.mpControlVector && rToBeCopied.mpControlVector->isUsed())
708cdf0e10cSrcweir 			mpControlVector.reset( new ControlVectorArray2D(*rToBeCopied.mpControlVector) );
709cdf0e10cSrcweir 
710cdf0e10cSrcweir         return *this;
711cdf0e10cSrcweir     }
712cdf0e10cSrcweir 
713cdf0e10cSrcweir 	sal_uInt32 count() const
714cdf0e10cSrcweir 	{
715cdf0e10cSrcweir 		return maPoints.count();
716cdf0e10cSrcweir 	}
717cdf0e10cSrcweir 
718cdf0e10cSrcweir 	bool isClosed() const
719cdf0e10cSrcweir 	{
720cdf0e10cSrcweir 		return mbIsClosed;
721cdf0e10cSrcweir 	}
722cdf0e10cSrcweir 
723cdf0e10cSrcweir 	void setClosed(bool bNew)
724cdf0e10cSrcweir 	{
725cdf0e10cSrcweir 		if(bNew != mbIsClosed)
726cdf0e10cSrcweir 		{
727cdf0e10cSrcweir 			mpBufferedData.reset();
728cdf0e10cSrcweir 			mbIsClosed = bNew;
729cdf0e10cSrcweir 		}
730cdf0e10cSrcweir 	}
731cdf0e10cSrcweir 
732cdf0e10cSrcweir 	bool operator==(const ImplB2DPolygon& rCandidate) const
733cdf0e10cSrcweir 	{
734cdf0e10cSrcweir 		if(mbIsClosed == rCandidate.mbIsClosed)
735cdf0e10cSrcweir 		{
736cdf0e10cSrcweir 			if(maPoints == rCandidate.maPoints)
737cdf0e10cSrcweir 			{
738cdf0e10cSrcweir 				bool bControlVectorsAreEqual(true);
739cdf0e10cSrcweir 
740cdf0e10cSrcweir 				if(mpControlVector)
741cdf0e10cSrcweir 				{
742cdf0e10cSrcweir 					if(rCandidate.mpControlVector)
743cdf0e10cSrcweir 					{
744cdf0e10cSrcweir 						bControlVectorsAreEqual = ((*mpControlVector) == (*rCandidate.mpControlVector));
745cdf0e10cSrcweir 					}
746cdf0e10cSrcweir 					else
747cdf0e10cSrcweir 					{
748cdf0e10cSrcweir 						// candidate has no control vector, so it's assumed all unused.
749cdf0e10cSrcweir 						bControlVectorsAreEqual = !mpControlVector->isUsed();
750cdf0e10cSrcweir 					}
751cdf0e10cSrcweir 				}
752cdf0e10cSrcweir 				else
753cdf0e10cSrcweir 				{
754cdf0e10cSrcweir 					if(rCandidate.mpControlVector)
755cdf0e10cSrcweir 					{
756cdf0e10cSrcweir 						// we have no control vector, so it's assumed all unused.
757cdf0e10cSrcweir 						bControlVectorsAreEqual = !rCandidate.mpControlVector->isUsed();
758cdf0e10cSrcweir 					}
759cdf0e10cSrcweir 				}
760cdf0e10cSrcweir 
761cdf0e10cSrcweir 				if(bControlVectorsAreEqual)
762cdf0e10cSrcweir 				{
763cdf0e10cSrcweir 					return true;
764cdf0e10cSrcweir 				}
765cdf0e10cSrcweir 			}
766cdf0e10cSrcweir 		}
767cdf0e10cSrcweir 
768cdf0e10cSrcweir 		return false;
769cdf0e10cSrcweir 	}
770cdf0e10cSrcweir 
771cdf0e10cSrcweir 	const basegfx::B2DPoint& getPoint(sal_uInt32 nIndex) const
772cdf0e10cSrcweir 	{
773cdf0e10cSrcweir 		return maPoints.getCoordinate(nIndex);
774cdf0e10cSrcweir 	}
775cdf0e10cSrcweir 
776cdf0e10cSrcweir 	void setPoint(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue)
777cdf0e10cSrcweir 	{
778cdf0e10cSrcweir 		mpBufferedData.reset();
779cdf0e10cSrcweir 		maPoints.setCoordinate(nIndex, rValue);
780cdf0e10cSrcweir 	}
781cdf0e10cSrcweir 
782cdf0e10cSrcweir 	void reserve(sal_uInt32 nCount)
783cdf0e10cSrcweir 	{
784cdf0e10cSrcweir 		maPoints.reserve(nCount);
785cdf0e10cSrcweir 	}
786cdf0e10cSrcweir 
787cdf0e10cSrcweir 	void append(const basegfx::B2DPoint& rPoint)
788cdf0e10cSrcweir 	{
789cdf0e10cSrcweir 		mpBufferedData.reset(); // TODO: is this needed?
790cdf0e10cSrcweir 		const CoordinateData2D aCoordinate(rPoint);
791cdf0e10cSrcweir 		maPoints.append(aCoordinate);
792cdf0e10cSrcweir 
793cdf0e10cSrcweir 		if(mpControlVector)
794cdf0e10cSrcweir 		{
795cdf0e10cSrcweir 			const ControlVectorPair2D aVectorPair;
796cdf0e10cSrcweir 			mpControlVector->append(aVectorPair);
797cdf0e10cSrcweir 		}
798cdf0e10cSrcweir 	}
799cdf0e10cSrcweir 
800cdf0e10cSrcweir 	void insert(sal_uInt32 nIndex, const basegfx::B2DPoint& rPoint, sal_uInt32 nCount)
801cdf0e10cSrcweir 	{
802cdf0e10cSrcweir 		if(nCount)
803cdf0e10cSrcweir 		{
804cdf0e10cSrcweir 			mpBufferedData.reset();
805cdf0e10cSrcweir 			CoordinateData2D aCoordinate(rPoint);
806cdf0e10cSrcweir 			maPoints.insert(nIndex, aCoordinate, nCount);
807cdf0e10cSrcweir 
808cdf0e10cSrcweir 			if(mpControlVector)
809cdf0e10cSrcweir 			{
810cdf0e10cSrcweir 				ControlVectorPair2D aVectorPair;
811cdf0e10cSrcweir 				mpControlVector->insert(nIndex, aVectorPair, nCount);
812cdf0e10cSrcweir 			}
813cdf0e10cSrcweir 		}
814cdf0e10cSrcweir 	}
815cdf0e10cSrcweir 
816cdf0e10cSrcweir 	const basegfx::B2DVector& getPrevControlVector(sal_uInt32 nIndex) const
817cdf0e10cSrcweir 	{
818cdf0e10cSrcweir 		if(mpControlVector)
819cdf0e10cSrcweir 		{
820cdf0e10cSrcweir 			return mpControlVector->getPrevVector(nIndex);
821cdf0e10cSrcweir 		}
822cdf0e10cSrcweir 		else
823cdf0e10cSrcweir 		{
824cdf0e10cSrcweir 			return basegfx::B2DVector::getEmptyVector();
825cdf0e10cSrcweir 		}
826cdf0e10cSrcweir 	}
827cdf0e10cSrcweir 
828cdf0e10cSrcweir 	void setPrevControlVector(sal_uInt32 nIndex, const basegfx::B2DVector& rValue)
829cdf0e10cSrcweir 	{
830cdf0e10cSrcweir 		if(!mpControlVector)
831cdf0e10cSrcweir 		{
832cdf0e10cSrcweir 			if(!rValue.equalZero())
833cdf0e10cSrcweir 			{
834cdf0e10cSrcweir 				mpBufferedData.reset();
835cdf0e10cSrcweir 				mpControlVector.reset( new ControlVectorArray2D(maPoints.count()) );
836cdf0e10cSrcweir 				mpControlVector->setPrevVector(nIndex, rValue);
837cdf0e10cSrcweir 			}
838cdf0e10cSrcweir 		}
839cdf0e10cSrcweir 		else
840cdf0e10cSrcweir 		{
841cdf0e10cSrcweir 			mpBufferedData.reset();
842cdf0e10cSrcweir 			mpControlVector->setPrevVector(nIndex, rValue);
843cdf0e10cSrcweir 
844cdf0e10cSrcweir 			if(!mpControlVector->isUsed())
845cdf0e10cSrcweir                 mpControlVector.reset();
846cdf0e10cSrcweir 		}
847cdf0e10cSrcweir 	}
848cdf0e10cSrcweir 
849cdf0e10cSrcweir 	const basegfx::B2DVector& getNextControlVector(sal_uInt32 nIndex) const
850cdf0e10cSrcweir 	{
851cdf0e10cSrcweir 		if(mpControlVector)
852cdf0e10cSrcweir 		{
853cdf0e10cSrcweir 			return mpControlVector->getNextVector(nIndex);
854cdf0e10cSrcweir 		}
855cdf0e10cSrcweir 		else
856cdf0e10cSrcweir 		{
857cdf0e10cSrcweir 			return basegfx::B2DVector::getEmptyVector();
858cdf0e10cSrcweir 		}
859cdf0e10cSrcweir 	}
860cdf0e10cSrcweir 
861cdf0e10cSrcweir 	void setNextControlVector(sal_uInt32 nIndex, const basegfx::B2DVector& rValue)
862cdf0e10cSrcweir 	{
863cdf0e10cSrcweir 		if(!mpControlVector)
864cdf0e10cSrcweir 		{
865cdf0e10cSrcweir 			if(!rValue.equalZero())
866cdf0e10cSrcweir 			{
867cdf0e10cSrcweir 				mpBufferedData.reset();
868cdf0e10cSrcweir 				mpControlVector.reset( new ControlVectorArray2D(maPoints.count()) );
869cdf0e10cSrcweir 				mpControlVector->setNextVector(nIndex, rValue);
870cdf0e10cSrcweir 			}
871cdf0e10cSrcweir 		}
872cdf0e10cSrcweir 		else
873cdf0e10cSrcweir 		{
874cdf0e10cSrcweir 			mpBufferedData.reset();
875cdf0e10cSrcweir 			mpControlVector->setNextVector(nIndex, rValue);
876cdf0e10cSrcweir 
877cdf0e10cSrcweir 			if(!mpControlVector->isUsed())
878cdf0e10cSrcweir                 mpControlVector.reset();
879cdf0e10cSrcweir 		}
880cdf0e10cSrcweir 	}
881cdf0e10cSrcweir 
882cdf0e10cSrcweir 	bool areControlPointsUsed() const
883cdf0e10cSrcweir 	{
884cdf0e10cSrcweir 		return (mpControlVector && mpControlVector->isUsed());
885cdf0e10cSrcweir 	}
886cdf0e10cSrcweir 
887cdf0e10cSrcweir 	void resetControlVectors(sal_uInt32 nIndex)
888cdf0e10cSrcweir 	{
889cdf0e10cSrcweir 		setPrevControlVector(nIndex, basegfx::B2DVector::getEmptyVector());
890cdf0e10cSrcweir 		setNextControlVector(nIndex, basegfx::B2DVector::getEmptyVector());
891cdf0e10cSrcweir 	}
892cdf0e10cSrcweir 
893cdf0e10cSrcweir 	void resetControlVectors()
894cdf0e10cSrcweir 	{
895cdf0e10cSrcweir 		mpBufferedData.reset();
896cdf0e10cSrcweir 		mpControlVector.reset();
897cdf0e10cSrcweir 	}
898cdf0e10cSrcweir 
899cdf0e10cSrcweir 	void setControlVectors(sal_uInt32 nIndex, const basegfx::B2DVector& rPrev, const basegfx::B2DVector& rNext)
900cdf0e10cSrcweir 	{
901cdf0e10cSrcweir 		setPrevControlVector(nIndex, rPrev);
902cdf0e10cSrcweir 		setNextControlVector(nIndex, rNext);
903cdf0e10cSrcweir 	}
904cdf0e10cSrcweir 
905cdf0e10cSrcweir 	void appendBezierSegment(const basegfx::B2DVector& rNext, const basegfx::B2DVector& rPrev, const basegfx::B2DPoint& rPoint)
906cdf0e10cSrcweir 	{
907cdf0e10cSrcweir 		mpBufferedData.reset();
908cdf0e10cSrcweir 		const sal_uInt32 nCount(maPoints.count());
909cdf0e10cSrcweir 
910cdf0e10cSrcweir         if(nCount)
911cdf0e10cSrcweir 		{
912cdf0e10cSrcweir 			setNextControlVector(nCount - 1, rNext);
913cdf0e10cSrcweir 		}
914cdf0e10cSrcweir 
915cdf0e10cSrcweir 		insert(nCount, rPoint, 1);
916cdf0e10cSrcweir 		setPrevControlVector(nCount, rPrev);
917cdf0e10cSrcweir 	}
918cdf0e10cSrcweir 
919cdf0e10cSrcweir 	void insert(sal_uInt32 nIndex, const ImplB2DPolygon& rSource)
920cdf0e10cSrcweir 	{
921cdf0e10cSrcweir 		const sal_uInt32 nCount(rSource.maPoints.count());
922cdf0e10cSrcweir 
923cdf0e10cSrcweir 		if(nCount)
924cdf0e10cSrcweir 		{
925cdf0e10cSrcweir 			mpBufferedData.reset();
926cdf0e10cSrcweir 
927cdf0e10cSrcweir 			if(rSource.mpControlVector && rSource.mpControlVector->isUsed() && !mpControlVector)
928cdf0e10cSrcweir 			{
929cdf0e10cSrcweir 				mpControlVector.reset( new ControlVectorArray2D(maPoints.count()) );
930cdf0e10cSrcweir 			}
931cdf0e10cSrcweir 
932cdf0e10cSrcweir 			maPoints.insert(nIndex, rSource.maPoints);
933cdf0e10cSrcweir 
934cdf0e10cSrcweir 			if(rSource.mpControlVector)
935cdf0e10cSrcweir 			{
936cdf0e10cSrcweir 				mpControlVector->insert(nIndex, *rSource.mpControlVector);
937cdf0e10cSrcweir 
938cdf0e10cSrcweir 				if(!mpControlVector->isUsed())
939cdf0e10cSrcweir                     mpControlVector.reset();
940cdf0e10cSrcweir 			}
941cdf0e10cSrcweir 			else if(mpControlVector)
942cdf0e10cSrcweir 			{
943cdf0e10cSrcweir 				ControlVectorPair2D aVectorPair;
944cdf0e10cSrcweir 				mpControlVector->insert(nIndex, aVectorPair, nCount);
945cdf0e10cSrcweir 			}
946cdf0e10cSrcweir 		}
947cdf0e10cSrcweir 	}
948cdf0e10cSrcweir 
949cdf0e10cSrcweir 	void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
950cdf0e10cSrcweir 	{
951cdf0e10cSrcweir 		if(nCount)
952cdf0e10cSrcweir 		{
953cdf0e10cSrcweir 			mpBufferedData.reset();
954cdf0e10cSrcweir 			maPoints.remove(nIndex, nCount);
955cdf0e10cSrcweir 
956cdf0e10cSrcweir 			if(mpControlVector)
957cdf0e10cSrcweir 			{
958cdf0e10cSrcweir 				mpControlVector->remove(nIndex, nCount);
959cdf0e10cSrcweir 
960cdf0e10cSrcweir 				if(!mpControlVector->isUsed())
961cdf0e10cSrcweir                     mpControlVector.reset();
962cdf0e10cSrcweir 			}
963cdf0e10cSrcweir 		}
964cdf0e10cSrcweir 	}
965cdf0e10cSrcweir 
966cdf0e10cSrcweir 	void flip()
967cdf0e10cSrcweir 	{
968cdf0e10cSrcweir 		if(maPoints.count() > 1)
969cdf0e10cSrcweir 		{
970cdf0e10cSrcweir 			mpBufferedData.reset();
971cdf0e10cSrcweir 
972cdf0e10cSrcweir 			// flip points
973cdf0e10cSrcweir 			maPoints.flip(mbIsClosed);
974cdf0e10cSrcweir 
975cdf0e10cSrcweir 			if(mpControlVector)
976cdf0e10cSrcweir 			{
977cdf0e10cSrcweir 				// flip control vector
978cdf0e10cSrcweir 				mpControlVector->flip(mbIsClosed);
979cdf0e10cSrcweir 			}
980cdf0e10cSrcweir 		}
981cdf0e10cSrcweir 	}
982cdf0e10cSrcweir 
983cdf0e10cSrcweir 	bool hasDoublePoints() const
984cdf0e10cSrcweir 	{
985cdf0e10cSrcweir 		if(mbIsClosed)
986cdf0e10cSrcweir 		{
987cdf0e10cSrcweir 			// check for same start and end point
988cdf0e10cSrcweir 			const sal_uInt32 nIndex(maPoints.count() - 1);
989cdf0e10cSrcweir 
990cdf0e10cSrcweir 			if(maPoints.getCoordinate(0) == maPoints.getCoordinate(nIndex))
991cdf0e10cSrcweir 			{
992cdf0e10cSrcweir 				if(mpControlVector)
993cdf0e10cSrcweir 				{
994cdf0e10cSrcweir 					if(mpControlVector->getNextVector(nIndex).equalZero() && mpControlVector->getPrevVector(0).equalZero())
995cdf0e10cSrcweir 					{
996cdf0e10cSrcweir 						return true;
997cdf0e10cSrcweir 					}
998cdf0e10cSrcweir 				}
999cdf0e10cSrcweir 				else
1000cdf0e10cSrcweir 				{
1001cdf0e10cSrcweir 					return true;
1002cdf0e10cSrcweir 				}
1003cdf0e10cSrcweir 			}
1004cdf0e10cSrcweir 		}
1005cdf0e10cSrcweir 
1006cdf0e10cSrcweir 		// test for range
1007cdf0e10cSrcweir 		for(sal_uInt32 a(0); a < maPoints.count() - 1; a++)
1008cdf0e10cSrcweir 		{
1009cdf0e10cSrcweir 			if(maPoints.getCoordinate(a) == maPoints.getCoordinate(a + 1))
1010cdf0e10cSrcweir 			{
1011cdf0e10cSrcweir 				if(mpControlVector)
1012cdf0e10cSrcweir 				{
1013cdf0e10cSrcweir 					if(mpControlVector->getNextVector(a).equalZero() && mpControlVector->getPrevVector(a + 1).equalZero())
1014cdf0e10cSrcweir 					{
1015cdf0e10cSrcweir 						return true;
1016cdf0e10cSrcweir 					}
1017cdf0e10cSrcweir 				}
1018cdf0e10cSrcweir 				else
1019cdf0e10cSrcweir 				{
1020cdf0e10cSrcweir 					return true;
1021cdf0e10cSrcweir 				}
1022cdf0e10cSrcweir 			}
1023cdf0e10cSrcweir 		}
1024cdf0e10cSrcweir 
1025cdf0e10cSrcweir 		return false;
1026cdf0e10cSrcweir 	}
1027cdf0e10cSrcweir 
1028cdf0e10cSrcweir 	void removeDoublePointsAtBeginEnd()
1029cdf0e10cSrcweir 	{
1030cdf0e10cSrcweir 		// Only remove DoublePoints at Begin and End when poly is closed
1031cdf0e10cSrcweir 		if(mbIsClosed)
1032cdf0e10cSrcweir 		{
1033cdf0e10cSrcweir 			mpBufferedData.reset();
1034cdf0e10cSrcweir 
1035cdf0e10cSrcweir             if(mpControlVector)
1036cdf0e10cSrcweir 			{
1037cdf0e10cSrcweir 				bool bRemove;
1038cdf0e10cSrcweir 
1039cdf0e10cSrcweir 				do
1040cdf0e10cSrcweir 				{
1041cdf0e10cSrcweir 					bRemove = false;
1042cdf0e10cSrcweir 
1043cdf0e10cSrcweir 					if(maPoints.count() > 1)
1044cdf0e10cSrcweir 					{
1045cdf0e10cSrcweir 						const sal_uInt32 nIndex(maPoints.count() - 1);
1046cdf0e10cSrcweir 
1047cdf0e10cSrcweir 						if(maPoints.getCoordinate(0) == maPoints.getCoordinate(nIndex))
1048cdf0e10cSrcweir 						{
1049cdf0e10cSrcweir 							if(mpControlVector)
1050cdf0e10cSrcweir 							{
1051cdf0e10cSrcweir 								if(mpControlVector->getNextVector(nIndex).equalZero() && mpControlVector->getPrevVector(0).equalZero())
1052cdf0e10cSrcweir 								{
1053cdf0e10cSrcweir 									bRemove = true;
1054cdf0e10cSrcweir 								}
1055cdf0e10cSrcweir 							}
1056cdf0e10cSrcweir 							else
1057cdf0e10cSrcweir 							{
1058cdf0e10cSrcweir 								bRemove = true;
1059cdf0e10cSrcweir 							}
1060cdf0e10cSrcweir 						}
1061cdf0e10cSrcweir 					}
1062cdf0e10cSrcweir 
1063cdf0e10cSrcweir 					if(bRemove)
1064cdf0e10cSrcweir 					{
1065cdf0e10cSrcweir 						const sal_uInt32 nIndex(maPoints.count() - 1);
1066cdf0e10cSrcweir 
1067cdf0e10cSrcweir 						if(mpControlVector && !mpControlVector->getPrevVector(nIndex).equalZero())
1068cdf0e10cSrcweir 						{
1069cdf0e10cSrcweir 							mpControlVector->setPrevVector(0, mpControlVector->getPrevVector(nIndex));
1070cdf0e10cSrcweir 						}
1071cdf0e10cSrcweir 
1072cdf0e10cSrcweir 						remove(nIndex, 1);
1073cdf0e10cSrcweir 					}
1074cdf0e10cSrcweir 				}
1075cdf0e10cSrcweir 				while(bRemove);
1076cdf0e10cSrcweir 			}
1077cdf0e10cSrcweir 			else
1078cdf0e10cSrcweir 			{
1079cdf0e10cSrcweir 				maPoints.removeDoublePointsAtBeginEnd();
1080cdf0e10cSrcweir 			}
1081cdf0e10cSrcweir 		}
1082cdf0e10cSrcweir 	}
1083cdf0e10cSrcweir 
1084cdf0e10cSrcweir 	void removeDoublePointsWholeTrack()
1085cdf0e10cSrcweir 	{
1086cdf0e10cSrcweir 		mpBufferedData.reset();
1087cdf0e10cSrcweir 
1088cdf0e10cSrcweir         if(mpControlVector)
1089cdf0e10cSrcweir 		{
1090cdf0e10cSrcweir 			sal_uInt32 nIndex(0);
1091cdf0e10cSrcweir 
1092cdf0e10cSrcweir 			// test as long as there are at least two points and as long as the index
1093cdf0e10cSrcweir 			// is smaller or equal second last point
1094cdf0e10cSrcweir 			while((maPoints.count() > 1) && (nIndex <= maPoints.count() - 2))
1095cdf0e10cSrcweir 			{
1096cdf0e10cSrcweir 				bool bRemove(maPoints.getCoordinate(nIndex) == maPoints.getCoordinate(nIndex + 1));
1097cdf0e10cSrcweir 
1098cdf0e10cSrcweir 				if(bRemove)
1099cdf0e10cSrcweir 				{
1100cdf0e10cSrcweir 					if(mpControlVector)
1101cdf0e10cSrcweir 					{
1102cdf0e10cSrcweir 						if(!mpControlVector->getNextVector(nIndex).equalZero() || !mpControlVector->getPrevVector(nIndex + 1).equalZero())
1103cdf0e10cSrcweir 						{
1104cdf0e10cSrcweir 							bRemove = false;
1105cdf0e10cSrcweir 						}
1106cdf0e10cSrcweir 					}
1107cdf0e10cSrcweir 				}
1108cdf0e10cSrcweir 
1109cdf0e10cSrcweir 				if(bRemove)
1110cdf0e10cSrcweir 				{
1111cdf0e10cSrcweir 					if(mpControlVector && !mpControlVector->getPrevVector(nIndex).equalZero())
1112cdf0e10cSrcweir 					{
1113cdf0e10cSrcweir 						mpControlVector->setPrevVector(nIndex + 1, mpControlVector->getPrevVector(nIndex));
1114cdf0e10cSrcweir 					}
1115cdf0e10cSrcweir 
1116cdf0e10cSrcweir 					// if next is same as index and the control vectors are unused, delete index
1117cdf0e10cSrcweir 					remove(nIndex, 1);
1118cdf0e10cSrcweir 				}
1119cdf0e10cSrcweir 				else
1120cdf0e10cSrcweir 				{
1121cdf0e10cSrcweir 					// if different, step forward
1122cdf0e10cSrcweir 					nIndex++;
1123cdf0e10cSrcweir 				}
1124cdf0e10cSrcweir 			}
1125cdf0e10cSrcweir 		}
1126cdf0e10cSrcweir 		else
1127cdf0e10cSrcweir 		{
1128cdf0e10cSrcweir 			maPoints.removeDoublePointsWholeTrack();
1129cdf0e10cSrcweir 		}
1130cdf0e10cSrcweir 	}
1131cdf0e10cSrcweir 
1132cdf0e10cSrcweir 	void transform(const basegfx::B2DHomMatrix& rMatrix)
1133cdf0e10cSrcweir 	{
1134cdf0e10cSrcweir 		mpBufferedData.reset();
1135cdf0e10cSrcweir 
1136cdf0e10cSrcweir         if(mpControlVector)
1137cdf0e10cSrcweir 		{
1138cdf0e10cSrcweir 			for(sal_uInt32 a(0); a < maPoints.count(); a++)
1139cdf0e10cSrcweir 			{
1140cdf0e10cSrcweir 				basegfx::B2DPoint aCandidate = maPoints.getCoordinate(a);
1141cdf0e10cSrcweir 
1142cdf0e10cSrcweir 				if(mpControlVector->isUsed())
1143cdf0e10cSrcweir 				{
1144cdf0e10cSrcweir 					const basegfx::B2DVector& rPrevVector(mpControlVector->getPrevVector(a));
1145cdf0e10cSrcweir 					const basegfx::B2DVector& rNextVector(mpControlVector->getNextVector(a));
1146cdf0e10cSrcweir 
1147cdf0e10cSrcweir 					if(!rPrevVector.equalZero())
1148cdf0e10cSrcweir 					{
1149cdf0e10cSrcweir 						basegfx::B2DVector aPrevVector(rMatrix * rPrevVector);
1150cdf0e10cSrcweir 						mpControlVector->setPrevVector(a, aPrevVector);
1151cdf0e10cSrcweir 					}
1152cdf0e10cSrcweir 
1153cdf0e10cSrcweir 					if(!rNextVector.equalZero())
1154cdf0e10cSrcweir 					{
1155cdf0e10cSrcweir 						basegfx::B2DVector aNextVector(rMatrix * rNextVector);
1156cdf0e10cSrcweir 						mpControlVector->setNextVector(a, aNextVector);
1157cdf0e10cSrcweir 					}
1158cdf0e10cSrcweir 				}
1159cdf0e10cSrcweir 
1160cdf0e10cSrcweir 				aCandidate *= rMatrix;
1161cdf0e10cSrcweir 				maPoints.setCoordinate(a, aCandidate);
1162cdf0e10cSrcweir 			}
1163cdf0e10cSrcweir 
1164cdf0e10cSrcweir 			if(!mpControlVector->isUsed())
1165cdf0e10cSrcweir                 mpControlVector.reset();
1166cdf0e10cSrcweir 		}
1167cdf0e10cSrcweir 		else
1168cdf0e10cSrcweir 		{
1169cdf0e10cSrcweir 			maPoints.transform(rMatrix);
1170cdf0e10cSrcweir 		}
1171cdf0e10cSrcweir 	}
1172cdf0e10cSrcweir 
1173cdf0e10cSrcweir     const basegfx::B2DPoint* begin() const
1174cdf0e10cSrcweir     {
1175cdf0e10cSrcweir         return maPoints.begin();
1176cdf0e10cSrcweir     }
1177cdf0e10cSrcweir 
1178cdf0e10cSrcweir     const basegfx::B2DPoint* end() const
1179cdf0e10cSrcweir     {
1180cdf0e10cSrcweir         return maPoints.end();
1181cdf0e10cSrcweir     }
1182cdf0e10cSrcweir 
1183cdf0e10cSrcweir     basegfx::B2DPoint* begin()
1184cdf0e10cSrcweir     {
1185cdf0e10cSrcweir        mpBufferedData.reset();
1186cdf0e10cSrcweir        return maPoints.begin();
1187cdf0e10cSrcweir     }
1188cdf0e10cSrcweir 
1189cdf0e10cSrcweir     basegfx::B2DPoint* end()
1190cdf0e10cSrcweir     {
1191cdf0e10cSrcweir         mpBufferedData.reset();
1192cdf0e10cSrcweir         return maPoints.end();
1193cdf0e10cSrcweir     }
1194cdf0e10cSrcweir };
1195cdf0e10cSrcweir 
1196cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
1197cdf0e10cSrcweir 
1198cdf0e10cSrcweir namespace basegfx
1199cdf0e10cSrcweir {
1200cdf0e10cSrcweir     namespace
1201cdf0e10cSrcweir 	{
1202cdf0e10cSrcweir 		struct DefaultPolygon: public rtl::Static<B2DPolygon::ImplType, DefaultPolygon> {};
1203cdf0e10cSrcweir 	}
1204cdf0e10cSrcweir 
1205cdf0e10cSrcweir 	B2DPolygon::B2DPolygon()
1206cdf0e10cSrcweir 	:	mpPolygon(DefaultPolygon::get())
1207cdf0e10cSrcweir 	{}
1208cdf0e10cSrcweir 
1209cdf0e10cSrcweir 	B2DPolygon::B2DPolygon(const B2DPolygon& rPolygon)
1210cdf0e10cSrcweir 	:	mpPolygon(rPolygon.mpPolygon)
1211cdf0e10cSrcweir 	{}
1212cdf0e10cSrcweir 
1213cdf0e10cSrcweir 	B2DPolygon::B2DPolygon(const B2DPolygon& rPolygon, sal_uInt32 nIndex, sal_uInt32 nCount)
1214cdf0e10cSrcweir 	:	mpPolygon(ImplB2DPolygon(*rPolygon.mpPolygon, nIndex, nCount))
1215cdf0e10cSrcweir 	{
1216cdf0e10cSrcweir         // TODO(P2): one extra temporary here (cow_wrapper copies
1217cdf0e10cSrcweir         // given ImplB2DPolygon into its internal impl_t wrapper type)
1218cdf0e10cSrcweir 		OSL_ENSURE(nIndex + nCount <= rPolygon.mpPolygon->count(), "B2DPolygon constructor outside range (!)");
1219cdf0e10cSrcweir 	}
1220cdf0e10cSrcweir 
1221cdf0e10cSrcweir 	B2DPolygon::~B2DPolygon()
1222cdf0e10cSrcweir 	{
1223cdf0e10cSrcweir 	}
1224cdf0e10cSrcweir 
1225cdf0e10cSrcweir 	B2DPolygon& B2DPolygon::operator=(const B2DPolygon& rPolygon)
1226cdf0e10cSrcweir 	{
1227cdf0e10cSrcweir 		mpPolygon = rPolygon.mpPolygon;
1228cdf0e10cSrcweir 		return *this;
1229cdf0e10cSrcweir 	}
1230cdf0e10cSrcweir 
1231cdf0e10cSrcweir     void B2DPolygon::makeUnique()
1232cdf0e10cSrcweir     {
1233cdf0e10cSrcweir         mpPolygon.make_unique();
1234cdf0e10cSrcweir     }
1235cdf0e10cSrcweir 
1236cdf0e10cSrcweir 	bool B2DPolygon::operator==(const B2DPolygon& rPolygon) const
1237cdf0e10cSrcweir 	{
1238cdf0e10cSrcweir 		if(mpPolygon.same_object(rPolygon.mpPolygon))
1239cdf0e10cSrcweir 			return true;
1240cdf0e10cSrcweir 
1241cdf0e10cSrcweir 		return ((*mpPolygon) == (*rPolygon.mpPolygon));
1242cdf0e10cSrcweir 	}
1243cdf0e10cSrcweir 
1244cdf0e10cSrcweir 	bool B2DPolygon::operator!=(const B2DPolygon& rPolygon) const
1245cdf0e10cSrcweir 	{
1246cdf0e10cSrcweir         return !(*this == rPolygon);
1247cdf0e10cSrcweir 	}
1248cdf0e10cSrcweir 
1249cdf0e10cSrcweir 	sal_uInt32 B2DPolygon::count() const
1250cdf0e10cSrcweir 	{
1251cdf0e10cSrcweir 		return mpPolygon->count();
1252cdf0e10cSrcweir 	}
1253cdf0e10cSrcweir 
1254cdf0e10cSrcweir     B2DPoint B2DPolygon::getB2DPoint(sal_uInt32 nIndex) const
1255cdf0e10cSrcweir 	{
1256cdf0e10cSrcweir 		OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1257cdf0e10cSrcweir 
1258cdf0e10cSrcweir 		return mpPolygon->getPoint(nIndex);
1259cdf0e10cSrcweir 	}
1260cdf0e10cSrcweir 
1261cdf0e10cSrcweir 	void B2DPolygon::setB2DPoint(sal_uInt32 nIndex, const B2DPoint& rValue)
1262cdf0e10cSrcweir 	{
1263cdf0e10cSrcweir 		OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1264cdf0e10cSrcweir 
1265cdf0e10cSrcweir 		if(getB2DPoint(nIndex) != rValue)
1266cdf0e10cSrcweir 		{
1267cdf0e10cSrcweir 			mpPolygon->setPoint(nIndex, rValue);
1268cdf0e10cSrcweir 		}
1269cdf0e10cSrcweir 	}
1270cdf0e10cSrcweir 
1271cdf0e10cSrcweir 	void B2DPolygon::reserve(sal_uInt32 nCount)
1272cdf0e10cSrcweir 	{
1273cdf0e10cSrcweir 		mpPolygon->reserve(nCount);
1274cdf0e10cSrcweir 	}
1275cdf0e10cSrcweir 
1276cdf0e10cSrcweir 	void B2DPolygon::insert(sal_uInt32 nIndex, const B2DPoint& rPoint, sal_uInt32 nCount)
1277cdf0e10cSrcweir 	{
1278cdf0e10cSrcweir 		OSL_ENSURE(nIndex <= mpPolygon->count(), "B2DPolygon Insert outside range (!)");
1279cdf0e10cSrcweir 
1280cdf0e10cSrcweir 		if(nCount)
1281cdf0e10cSrcweir 		{
1282cdf0e10cSrcweir 			mpPolygon->insert(nIndex, rPoint, nCount);
1283cdf0e10cSrcweir 		}
1284cdf0e10cSrcweir 	}
1285cdf0e10cSrcweir 
1286cdf0e10cSrcweir 	void B2DPolygon::append(const B2DPoint& rPoint, sal_uInt32 nCount)
1287cdf0e10cSrcweir 	{
1288cdf0e10cSrcweir 		if(nCount)
1289cdf0e10cSrcweir 		{
1290cdf0e10cSrcweir 			mpPolygon->insert(mpPolygon->count(), rPoint, nCount);
1291cdf0e10cSrcweir 		}
1292cdf0e10cSrcweir 	}
1293cdf0e10cSrcweir 
1294cdf0e10cSrcweir 	void B2DPolygon::append(const B2DPoint& rPoint)
1295cdf0e10cSrcweir 	{
1296cdf0e10cSrcweir 		mpPolygon->append(rPoint);
1297cdf0e10cSrcweir 	}
1298cdf0e10cSrcweir 
1299cdf0e10cSrcweir 	B2DPoint B2DPolygon::getPrevControlPoint(sal_uInt32 nIndex) const
1300cdf0e10cSrcweir 	{
1301cdf0e10cSrcweir 		OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1302cdf0e10cSrcweir 
1303cdf0e10cSrcweir 		if(mpPolygon->areControlPointsUsed())
1304cdf0e10cSrcweir 		{
1305cdf0e10cSrcweir 			return mpPolygon->getPoint(nIndex) + mpPolygon->getPrevControlVector(nIndex);
1306cdf0e10cSrcweir 		}
1307cdf0e10cSrcweir 		else
1308cdf0e10cSrcweir 		{
1309cdf0e10cSrcweir 			return mpPolygon->getPoint(nIndex);
1310cdf0e10cSrcweir 		}
1311cdf0e10cSrcweir 	}
1312cdf0e10cSrcweir 
1313cdf0e10cSrcweir 	B2DPoint B2DPolygon::getNextControlPoint(sal_uInt32 nIndex) const
1314cdf0e10cSrcweir 	{
1315cdf0e10cSrcweir 		OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1316cdf0e10cSrcweir 
1317cdf0e10cSrcweir 		if(mpPolygon->areControlPointsUsed())
1318cdf0e10cSrcweir 		{
1319cdf0e10cSrcweir 			return mpPolygon->getPoint(nIndex) + mpPolygon->getNextControlVector(nIndex);
1320cdf0e10cSrcweir 		}
1321cdf0e10cSrcweir 		else
1322cdf0e10cSrcweir 		{
1323cdf0e10cSrcweir 			return mpPolygon->getPoint(nIndex);
1324cdf0e10cSrcweir 		}
1325cdf0e10cSrcweir 	}
1326cdf0e10cSrcweir 
1327cdf0e10cSrcweir 	void B2DPolygon::setPrevControlPoint(sal_uInt32 nIndex, const B2DPoint& rValue)
1328cdf0e10cSrcweir 	{
1329cdf0e10cSrcweir 		OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1330cdf0e10cSrcweir 		const basegfx::B2DVector aNewVector(rValue - mpPolygon->getPoint(nIndex));
1331cdf0e10cSrcweir 
1332cdf0e10cSrcweir 		if(mpPolygon->getPrevControlVector(nIndex) != aNewVector)
1333cdf0e10cSrcweir 		{
1334cdf0e10cSrcweir 			mpPolygon->setPrevControlVector(nIndex, aNewVector);
1335cdf0e10cSrcweir 		}
1336cdf0e10cSrcweir 	}
1337cdf0e10cSrcweir 
1338cdf0e10cSrcweir 	void B2DPolygon::setNextControlPoint(sal_uInt32 nIndex, const B2DPoint& rValue)
1339cdf0e10cSrcweir 	{
1340cdf0e10cSrcweir 		OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1341cdf0e10cSrcweir 		const basegfx::B2DVector aNewVector(rValue - mpPolygon->getPoint(nIndex));
1342cdf0e10cSrcweir 
1343cdf0e10cSrcweir 		if(mpPolygon->getNextControlVector(nIndex) != aNewVector)
1344cdf0e10cSrcweir 		{
1345cdf0e10cSrcweir 			mpPolygon->setNextControlVector(nIndex, aNewVector);
1346cdf0e10cSrcweir 		}
1347cdf0e10cSrcweir 	}
1348cdf0e10cSrcweir 
1349cdf0e10cSrcweir 	void B2DPolygon::setControlPoints(sal_uInt32 nIndex, const basegfx::B2DPoint& rPrev, const basegfx::B2DPoint& rNext)
1350cdf0e10cSrcweir 	{
1351cdf0e10cSrcweir 		OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1352cdf0e10cSrcweir 		const B2DPoint aPoint(mpPolygon->getPoint(nIndex));
1353cdf0e10cSrcweir 		const basegfx::B2DVector aNewPrev(rPrev - aPoint);
1354cdf0e10cSrcweir 		const basegfx::B2DVector aNewNext(rNext - aPoint);
1355cdf0e10cSrcweir 
1356cdf0e10cSrcweir 		if(mpPolygon->getPrevControlVector(nIndex) != aNewPrev || mpPolygon->getNextControlVector(nIndex) != aNewNext)
1357cdf0e10cSrcweir 		{
1358cdf0e10cSrcweir 			mpPolygon->setControlVectors(nIndex, aNewPrev, aNewNext);
1359cdf0e10cSrcweir 		}
1360cdf0e10cSrcweir 	}
1361cdf0e10cSrcweir 
1362cdf0e10cSrcweir 	void B2DPolygon::resetPrevControlPoint(sal_uInt32 nIndex)
1363cdf0e10cSrcweir 	{
1364cdf0e10cSrcweir 		OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1365cdf0e10cSrcweir 
1366cdf0e10cSrcweir 		if(mpPolygon->areControlPointsUsed() && !mpPolygon->getPrevControlVector(nIndex).equalZero())
1367cdf0e10cSrcweir 		{
1368cdf0e10cSrcweir 			mpPolygon->setPrevControlVector(nIndex, B2DVector::getEmptyVector());
1369cdf0e10cSrcweir 		}
1370cdf0e10cSrcweir 	}
1371cdf0e10cSrcweir 
1372cdf0e10cSrcweir 	void B2DPolygon::resetNextControlPoint(sal_uInt32 nIndex)
1373cdf0e10cSrcweir 	{
1374cdf0e10cSrcweir 		OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1375cdf0e10cSrcweir 
1376cdf0e10cSrcweir 		if(mpPolygon->areControlPointsUsed() && !mpPolygon->getNextControlVector(nIndex).equalZero())
1377cdf0e10cSrcweir 		{
1378cdf0e10cSrcweir 			mpPolygon->setNextControlVector(nIndex, B2DVector::getEmptyVector());
1379cdf0e10cSrcweir 		}
1380cdf0e10cSrcweir 	}
1381cdf0e10cSrcweir 
1382cdf0e10cSrcweir 	void B2DPolygon::resetControlPoints(sal_uInt32 nIndex)
1383cdf0e10cSrcweir 	{
1384cdf0e10cSrcweir 		OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1385cdf0e10cSrcweir 
1386cdf0e10cSrcweir 		if(mpPolygon->areControlPointsUsed() &&
1387cdf0e10cSrcweir 			(!mpPolygon->getPrevControlVector(nIndex).equalZero() || !mpPolygon->getNextControlVector(nIndex).equalZero()))
1388cdf0e10cSrcweir 		{
1389cdf0e10cSrcweir 			mpPolygon->resetControlVectors(nIndex);
1390cdf0e10cSrcweir 		}
1391cdf0e10cSrcweir 	}
1392cdf0e10cSrcweir 
1393cdf0e10cSrcweir 	void B2DPolygon::resetControlPoints()
1394cdf0e10cSrcweir 	{
1395cdf0e10cSrcweir 		if(mpPolygon->areControlPointsUsed())
1396cdf0e10cSrcweir 		{
1397cdf0e10cSrcweir 			mpPolygon->resetControlVectors();
1398cdf0e10cSrcweir 		}
1399cdf0e10cSrcweir 	}
1400cdf0e10cSrcweir 
1401cdf0e10cSrcweir 	void B2DPolygon::appendBezierSegment(
1402cdf0e10cSrcweir 		const B2DPoint& rNextControlPoint,
1403cdf0e10cSrcweir 		const B2DPoint& rPrevControlPoint,
1404cdf0e10cSrcweir 		const B2DPoint& rPoint)
1405cdf0e10cSrcweir 	{
1406cdf0e10cSrcweir 		const B2DVector aNewNextVector(mpPolygon->count() ? B2DVector(rNextControlPoint - mpPolygon->getPoint(mpPolygon->count() - 1)) : B2DVector::getEmptyVector());
1407cdf0e10cSrcweir 		const B2DVector aNewPrevVector(rPrevControlPoint - rPoint);
1408cdf0e10cSrcweir 
1409cdf0e10cSrcweir 		if(aNewNextVector.equalZero() && aNewPrevVector.equalZero())
1410cdf0e10cSrcweir 		{
1411cdf0e10cSrcweir 			mpPolygon->insert(mpPolygon->count(), rPoint, 1);
1412cdf0e10cSrcweir 		}
1413cdf0e10cSrcweir 		else
1414cdf0e10cSrcweir 		{
1415cdf0e10cSrcweir 			mpPolygon->appendBezierSegment(aNewNextVector, aNewPrevVector, rPoint);
1416cdf0e10cSrcweir 		}
1417cdf0e10cSrcweir 	}
1418cdf0e10cSrcweir 
1419cdf0e10cSrcweir 	bool B2DPolygon::areControlPointsUsed() const
1420cdf0e10cSrcweir 	{
1421cdf0e10cSrcweir 		return mpPolygon->areControlPointsUsed();
1422cdf0e10cSrcweir 	}
1423cdf0e10cSrcweir 
1424cdf0e10cSrcweir 	bool B2DPolygon::isPrevControlPointUsed(sal_uInt32 nIndex) const
1425cdf0e10cSrcweir 	{
1426cdf0e10cSrcweir 		OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1427cdf0e10cSrcweir 
1428cdf0e10cSrcweir 		return (mpPolygon->areControlPointsUsed() && !mpPolygon->getPrevControlVector(nIndex).equalZero());
1429cdf0e10cSrcweir 	}
1430cdf0e10cSrcweir 
1431cdf0e10cSrcweir 	bool B2DPolygon::isNextControlPointUsed(sal_uInt32 nIndex) const
1432cdf0e10cSrcweir 	{
1433cdf0e10cSrcweir 		OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1434cdf0e10cSrcweir 
1435cdf0e10cSrcweir 		return (mpPolygon->areControlPointsUsed() && !mpPolygon->getNextControlVector(nIndex).equalZero());
1436cdf0e10cSrcweir 	}
1437cdf0e10cSrcweir 
1438cdf0e10cSrcweir 	B2VectorContinuity B2DPolygon::getContinuityInPoint(sal_uInt32 nIndex) const
1439cdf0e10cSrcweir 	{
1440cdf0e10cSrcweir 		OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1441cdf0e10cSrcweir 
1442cdf0e10cSrcweir 		if(mpPolygon->areControlPointsUsed())
1443cdf0e10cSrcweir 		{
1444cdf0e10cSrcweir 			const B2DVector& rPrev(mpPolygon->getPrevControlVector(nIndex));
1445cdf0e10cSrcweir 			const B2DVector& rNext(mpPolygon->getNextControlVector(nIndex));
1446cdf0e10cSrcweir 
1447cdf0e10cSrcweir 			return getContinuity(rPrev, rNext);
1448cdf0e10cSrcweir 		}
1449cdf0e10cSrcweir 		else
1450cdf0e10cSrcweir 		{
1451cdf0e10cSrcweir 			return CONTINUITY_NONE;
1452cdf0e10cSrcweir 		}
1453cdf0e10cSrcweir 	}
1454cdf0e10cSrcweir 
1455cdf0e10cSrcweir     bool B2DPolygon::isBezierSegment(sal_uInt32 nIndex) const
1456cdf0e10cSrcweir     {
1457cdf0e10cSrcweir 		OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1458cdf0e10cSrcweir 
1459cdf0e10cSrcweir         if(mpPolygon->areControlPointsUsed())
1460cdf0e10cSrcweir 		{
1461cdf0e10cSrcweir             // Check if the edge exists
1462cdf0e10cSrcweir             const bool bNextIndexValidWithoutClose(nIndex + 1 < mpPolygon->count());
1463cdf0e10cSrcweir 
1464cdf0e10cSrcweir             if(bNextIndexValidWithoutClose || mpPolygon->isClosed())
1465cdf0e10cSrcweir             {
1466cdf0e10cSrcweir                 const sal_uInt32 nNextIndex(bNextIndexValidWithoutClose ? nIndex + 1 : 0);
1467cdf0e10cSrcweir                 return (!mpPolygon->getPrevControlVector(nNextIndex).equalZero()
1468cdf0e10cSrcweir                     || !mpPolygon->getNextControlVector(nIndex).equalZero());
1469cdf0e10cSrcweir             }
1470cdf0e10cSrcweir             else
1471cdf0e10cSrcweir             {
1472cdf0e10cSrcweir                 // no valid edge -> no bezier segment, even when local next
1473cdf0e10cSrcweir                 // vector may be used
1474cdf0e10cSrcweir                 return false;
1475cdf0e10cSrcweir             }
1476cdf0e10cSrcweir         }
1477cdf0e10cSrcweir         else
1478cdf0e10cSrcweir         {
1479cdf0e10cSrcweir             // no control points -> no bezier segment
1480cdf0e10cSrcweir             return false;
1481cdf0e10cSrcweir         }
1482cdf0e10cSrcweir     }
1483cdf0e10cSrcweir 
1484cdf0e10cSrcweir     void B2DPolygon::getBezierSegment(sal_uInt32 nIndex, B2DCubicBezier& rTarget) const
1485cdf0e10cSrcweir     {
1486cdf0e10cSrcweir 		OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1487cdf0e10cSrcweir         const bool bNextIndexValidWithoutClose(nIndex + 1 < mpPolygon->count());
1488cdf0e10cSrcweir 
1489cdf0e10cSrcweir         if(bNextIndexValidWithoutClose || mpPolygon->isClosed())
1490cdf0e10cSrcweir         {
1491cdf0e10cSrcweir             const sal_uInt32 nNextIndex(bNextIndexValidWithoutClose ? nIndex + 1 : 0);
1492cdf0e10cSrcweir             rTarget.setStartPoint(mpPolygon->getPoint(nIndex));
1493cdf0e10cSrcweir             rTarget.setEndPoint(mpPolygon->getPoint(nNextIndex));
1494cdf0e10cSrcweir 
1495cdf0e10cSrcweir             if(mpPolygon->areControlPointsUsed())
1496cdf0e10cSrcweir             {
1497cdf0e10cSrcweir                 rTarget.setControlPointA(rTarget.getStartPoint() + mpPolygon->getNextControlVector(nIndex));
1498cdf0e10cSrcweir                 rTarget.setControlPointB(rTarget.getEndPoint() + mpPolygon->getPrevControlVector(nNextIndex));
1499cdf0e10cSrcweir             }
1500cdf0e10cSrcweir             else
1501cdf0e10cSrcweir             {
1502cdf0e10cSrcweir                 // no bezier, reset control poins at rTarget
1503cdf0e10cSrcweir                 rTarget.setControlPointA(rTarget.getStartPoint());
1504cdf0e10cSrcweir                 rTarget.setControlPointB(rTarget.getEndPoint());
1505cdf0e10cSrcweir             }
1506cdf0e10cSrcweir         }
1507cdf0e10cSrcweir         else
1508cdf0e10cSrcweir         {
1509cdf0e10cSrcweir             // no valid edge at all, reset rTarget to current point
1510cdf0e10cSrcweir     		const B2DPoint aPoint(mpPolygon->getPoint(nIndex));
1511cdf0e10cSrcweir             rTarget.setStartPoint(aPoint);
1512cdf0e10cSrcweir             rTarget.setEndPoint(aPoint);
1513cdf0e10cSrcweir             rTarget.setControlPointA(aPoint);
1514cdf0e10cSrcweir             rTarget.setControlPointB(aPoint);
1515cdf0e10cSrcweir         }
1516cdf0e10cSrcweir     }
1517cdf0e10cSrcweir 
1518cdf0e10cSrcweir     B2DPolygon B2DPolygon::getDefaultAdaptiveSubdivision() const
1519cdf0e10cSrcweir 	{
1520cdf0e10cSrcweir 		return mpPolygon->getDefaultAdaptiveSubdivision(*this);
1521cdf0e10cSrcweir 	}
1522cdf0e10cSrcweir 
1523cdf0e10cSrcweir     B2DRange B2DPolygon::getB2DRange() const
1524cdf0e10cSrcweir 	{
1525cdf0e10cSrcweir 		return mpPolygon->getB2DRange(*this);
1526cdf0e10cSrcweir 	}
1527cdf0e10cSrcweir 
1528cdf0e10cSrcweir 	void B2DPolygon::insert(sal_uInt32 nIndex, const B2DPolygon& rPoly, sal_uInt32 nIndex2, sal_uInt32 nCount)
1529cdf0e10cSrcweir 	{
1530cdf0e10cSrcweir 		OSL_ENSURE(nIndex <= mpPolygon->count(), "B2DPolygon Insert outside range (!)");
1531cdf0e10cSrcweir 
1532cdf0e10cSrcweir 		if(rPoly.count())
1533cdf0e10cSrcweir 		{
1534cdf0e10cSrcweir 			if(!nCount)
1535cdf0e10cSrcweir 			{
1536cdf0e10cSrcweir 				nCount = rPoly.count();
1537cdf0e10cSrcweir 			}
1538cdf0e10cSrcweir 
1539cdf0e10cSrcweir 			if(0 == nIndex2 && nCount == rPoly.count())
1540cdf0e10cSrcweir 			{
1541cdf0e10cSrcweir 				mpPolygon->insert(nIndex, *rPoly.mpPolygon);
1542cdf0e10cSrcweir 			}
1543cdf0e10cSrcweir 			else
1544cdf0e10cSrcweir 			{
1545cdf0e10cSrcweir 				OSL_ENSURE(nIndex2 + nCount <= rPoly.mpPolygon->count(), "B2DPolygon Insert outside range (!)");
1546cdf0e10cSrcweir 				ImplB2DPolygon aTempPoly(*rPoly.mpPolygon, nIndex2, nCount);
1547cdf0e10cSrcweir 				mpPolygon->insert(nIndex, aTempPoly);
1548cdf0e10cSrcweir 			}
1549cdf0e10cSrcweir 		}
1550cdf0e10cSrcweir 	}
1551cdf0e10cSrcweir 
1552cdf0e10cSrcweir 	void B2DPolygon::append(const B2DPolygon& rPoly, sal_uInt32 nIndex, sal_uInt32 nCount)
1553cdf0e10cSrcweir 	{
1554cdf0e10cSrcweir 		if(rPoly.count())
1555cdf0e10cSrcweir 		{
1556cdf0e10cSrcweir 			if(!nCount)
1557cdf0e10cSrcweir 			{
1558cdf0e10cSrcweir 				nCount = rPoly.count();
1559cdf0e10cSrcweir 			}
1560cdf0e10cSrcweir 
1561cdf0e10cSrcweir 			if(0 == nIndex && nCount == rPoly.count())
1562cdf0e10cSrcweir 			{
1563cdf0e10cSrcweir 				mpPolygon->insert(mpPolygon->count(), *rPoly.mpPolygon);
1564cdf0e10cSrcweir 			}
1565cdf0e10cSrcweir 			else
1566cdf0e10cSrcweir 			{
1567cdf0e10cSrcweir 				OSL_ENSURE(nIndex + nCount <= rPoly.mpPolygon->count(), "B2DPolygon Append outside range (!)");
1568cdf0e10cSrcweir 				ImplB2DPolygon aTempPoly(*rPoly.mpPolygon, nIndex, nCount);
1569cdf0e10cSrcweir 				mpPolygon->insert(mpPolygon->count(), aTempPoly);
1570cdf0e10cSrcweir 			}
1571cdf0e10cSrcweir 		}
1572cdf0e10cSrcweir 	}
1573cdf0e10cSrcweir 
1574cdf0e10cSrcweir 	void B2DPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount)
1575cdf0e10cSrcweir 	{
1576cdf0e10cSrcweir 		OSL_ENSURE(nIndex + nCount <= mpPolygon->count(), "B2DPolygon Remove outside range (!)");
1577cdf0e10cSrcweir 
1578cdf0e10cSrcweir 		if(nCount)
1579cdf0e10cSrcweir 		{
1580cdf0e10cSrcweir 			mpPolygon->remove(nIndex, nCount);
1581cdf0e10cSrcweir 		}
1582cdf0e10cSrcweir 	}
1583cdf0e10cSrcweir 
1584cdf0e10cSrcweir 	void B2DPolygon::clear()
1585cdf0e10cSrcweir 	{
1586cdf0e10cSrcweir 		mpPolygon = DefaultPolygon::get();
1587cdf0e10cSrcweir 	}
1588cdf0e10cSrcweir 
1589cdf0e10cSrcweir 	bool B2DPolygon::isClosed() const
1590cdf0e10cSrcweir 	{
1591cdf0e10cSrcweir 		return mpPolygon->isClosed();
1592cdf0e10cSrcweir 	}
1593cdf0e10cSrcweir 
1594cdf0e10cSrcweir 	void B2DPolygon::setClosed(bool bNew)
1595cdf0e10cSrcweir 	{
1596cdf0e10cSrcweir 		if(isClosed() != bNew)
1597cdf0e10cSrcweir 		{
1598cdf0e10cSrcweir 			mpPolygon->setClosed(bNew);
1599cdf0e10cSrcweir 		}
1600cdf0e10cSrcweir 	}
1601cdf0e10cSrcweir 
1602cdf0e10cSrcweir 	void B2DPolygon::flip()
1603cdf0e10cSrcweir 	{
1604cdf0e10cSrcweir 		if(count() > 1)
1605cdf0e10cSrcweir 		{
1606cdf0e10cSrcweir 			mpPolygon->flip();
1607cdf0e10cSrcweir 		}
1608cdf0e10cSrcweir 	}
1609cdf0e10cSrcweir 
1610cdf0e10cSrcweir 	bool B2DPolygon::hasDoublePoints() const
1611cdf0e10cSrcweir 	{
1612cdf0e10cSrcweir 		return (mpPolygon->count() > 1 && mpPolygon->hasDoublePoints());
1613cdf0e10cSrcweir 	}
1614cdf0e10cSrcweir 
1615cdf0e10cSrcweir 	void B2DPolygon::removeDoublePoints()
1616cdf0e10cSrcweir 	{
1617cdf0e10cSrcweir 		if(hasDoublePoints())
1618cdf0e10cSrcweir 		{
1619cdf0e10cSrcweir 			mpPolygon->removeDoublePointsAtBeginEnd();
1620cdf0e10cSrcweir 			mpPolygon->removeDoublePointsWholeTrack();
1621cdf0e10cSrcweir 		}
1622cdf0e10cSrcweir 	}
1623cdf0e10cSrcweir 
1624cdf0e10cSrcweir 	void B2DPolygon::transform(const B2DHomMatrix& rMatrix)
1625cdf0e10cSrcweir 	{
1626cdf0e10cSrcweir 		if(mpPolygon->count() && !rMatrix.isIdentity())
1627cdf0e10cSrcweir 		{
1628cdf0e10cSrcweir 			mpPolygon->transform(rMatrix);
1629cdf0e10cSrcweir 		}
1630cdf0e10cSrcweir 	}
1631cdf0e10cSrcweir 
1632cdf0e10cSrcweir     const B2DPoint* B2DPolygon::begin() const
1633cdf0e10cSrcweir     {
1634cdf0e10cSrcweir         return mpPolygon->begin();
1635cdf0e10cSrcweir     }
1636cdf0e10cSrcweir 
1637cdf0e10cSrcweir     const B2DPoint* B2DPolygon::end() const
1638cdf0e10cSrcweir     {
1639cdf0e10cSrcweir         return mpPolygon->end();
1640cdf0e10cSrcweir     }
1641cdf0e10cSrcweir 
1642cdf0e10cSrcweir     B2DPoint* B2DPolygon::begin()
1643cdf0e10cSrcweir     {
1644cdf0e10cSrcweir         return mpPolygon->begin();
1645cdf0e10cSrcweir     }
1646cdf0e10cSrcweir 
1647cdf0e10cSrcweir     B2DPoint* B2DPolygon::end()
1648cdf0e10cSrcweir     {
1649cdf0e10cSrcweir         return mpPolygon->end();
1650cdf0e10cSrcweir     }
1651cdf0e10cSrcweir } // end of namespace basegfx
1652cdf0e10cSrcweir 
1653cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
1654cdf0e10cSrcweir // eof
1655