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