xref: /AOO41X/main/tools/source/generic/poly.cxx (revision 89b56da77b74925c286b3e777681ba8dda16bf41)
1*89b56da7SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*89b56da7SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*89b56da7SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*89b56da7SAndrew Rist  * distributed with this work for additional information
6*89b56da7SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*89b56da7SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*89b56da7SAndrew Rist  * "License"); you may not use this file except in compliance
9*89b56da7SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11*89b56da7SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13*89b56da7SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*89b56da7SAndrew Rist  * software distributed under the License is distributed on an
15*89b56da7SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*89b56da7SAndrew Rist  * KIND, either express or implied.  See the License for the
17*89b56da7SAndrew Rist  * specific language governing permissions and limitations
18*89b56da7SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20*89b56da7SAndrew Rist  *************************************************************/
21*89b56da7SAndrew Rist 
22*89b56da7SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_tools.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #define _SV_POLY_CXX
28cdf0e10cSrcweir #include <osl/endian.h>
29cdf0e10cSrcweir #include <tools/bigint.hxx>
30cdf0e10cSrcweir #include <tools/debug.hxx>
31cdf0e10cSrcweir #include <tools/stream.hxx>
32cdf0e10cSrcweir #include <tools/vcompat.hxx>
33cdf0e10cSrcweir #include <poly.h>
34cdf0e10cSrcweir #include <tools/line.hxx>
35cdf0e10cSrcweir #ifndef _VECTOR2D_H
36cdf0e10cSrcweir #include <tools/vector2d.hxx>
37cdf0e10cSrcweir #endif
38cdf0e10cSrcweir #ifndef _POLY_HXX
39cdf0e10cSrcweir #include <tools/poly.hxx>
40cdf0e10cSrcweir #endif
41cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygon.hxx>
42cdf0e10cSrcweir #include <basegfx/point/b2dpoint.hxx>
43cdf0e10cSrcweir #include <basegfx/vector/b2dvector.hxx>
44cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx>
45cdf0e10cSrcweir #include <basegfx/curve/b2dcubicbezier.hxx>
46cdf0e10cSrcweir 
47cdf0e10cSrcweir #include <vector>
48cdf0e10cSrcweir #include <iterator>
49cdf0e10cSrcweir #include <algorithm>
50cdf0e10cSrcweir #include <cstring>
51cdf0e10cSrcweir #include <limits.h>
52cdf0e10cSrcweir #include <cmath>
53cdf0e10cSrcweir 
54cdf0e10cSrcweir 
55cdf0e10cSrcweir // =======================================================================
56cdf0e10cSrcweir 
57cdf0e10cSrcweir DBG_NAME( Polygon )
58cdf0e10cSrcweir 
59cdf0e10cSrcweir // -----------------------------------------------------------------------
60cdf0e10cSrcweir 
61cdf0e10cSrcweir #define EDGE_LEFT		1
62cdf0e10cSrcweir #define EDGE_TOP		2
63cdf0e10cSrcweir #define EDGE_RIGHT		4
64cdf0e10cSrcweir #define EDGE_BOTTOM 	8
65cdf0e10cSrcweir #define EDGE_HORZ		(EDGE_RIGHT | EDGE_LEFT)
66cdf0e10cSrcweir #define EDGE_VERT		(EDGE_TOP | EDGE_BOTTOM)
67cdf0e10cSrcweir #define	SMALL_DVALUE	0.0000001
68cdf0e10cSrcweir #define FSQRT2			1.4142135623730950488016887242097
69cdf0e10cSrcweir 
70cdf0e10cSrcweir // -----------------------------------------------------------------------
71cdf0e10cSrcweir 
72cdf0e10cSrcweir static ImplPolygonData aStaticImplPolygon =
73cdf0e10cSrcweir {
74cdf0e10cSrcweir 	NULL, NULL, 0, 0
75cdf0e10cSrcweir };
76cdf0e10cSrcweir 
77cdf0e10cSrcweir // =======================================================================
78cdf0e10cSrcweir 
79cdf0e10cSrcweir ImplPolygon::ImplPolygon( sal_uInt16 nInitSize, sal_Bool bFlags  )
80cdf0e10cSrcweir {
81cdf0e10cSrcweir 	if ( nInitSize )
82cdf0e10cSrcweir 	{
83cdf0e10cSrcweir 		mpPointAry = (Point*)new char[(sal_uIntPtr)nInitSize*sizeof(Point)];
84cdf0e10cSrcweir 		memset( mpPointAry, 0, (sal_uIntPtr)nInitSize*sizeof(Point) );
85cdf0e10cSrcweir 	}
86cdf0e10cSrcweir 	else
87cdf0e10cSrcweir 		mpPointAry = NULL;
88cdf0e10cSrcweir 
89cdf0e10cSrcweir 	if( bFlags )
90cdf0e10cSrcweir 	{
91cdf0e10cSrcweir 		mpFlagAry = new sal_uInt8[ nInitSize ];
92cdf0e10cSrcweir 		memset( mpPointAry, 0, nInitSize );
93cdf0e10cSrcweir 	}
94cdf0e10cSrcweir 	else
95cdf0e10cSrcweir 		mpFlagAry = NULL;
96cdf0e10cSrcweir 
97cdf0e10cSrcweir 	mnRefCount = 1;
98cdf0e10cSrcweir 	mnPoints = nInitSize;
99cdf0e10cSrcweir }
100cdf0e10cSrcweir 
101cdf0e10cSrcweir // -----------------------------------------------------------------------
102cdf0e10cSrcweir 
103cdf0e10cSrcweir ImplPolygon::ImplPolygon( const ImplPolygon& rImpPoly )
104cdf0e10cSrcweir {
105cdf0e10cSrcweir 	if ( rImpPoly.mnPoints )
106cdf0e10cSrcweir 	{
107cdf0e10cSrcweir 		mpPointAry = (Point*)new char[(sal_uIntPtr)rImpPoly.mnPoints*sizeof(Point)];
108cdf0e10cSrcweir 		memcpy( mpPointAry, rImpPoly.mpPointAry, (sal_uIntPtr)rImpPoly.mnPoints*sizeof(Point) );
109cdf0e10cSrcweir 
110cdf0e10cSrcweir 		if( rImpPoly.mpFlagAry )
111cdf0e10cSrcweir 		{
112cdf0e10cSrcweir 			mpFlagAry = new sal_uInt8[ rImpPoly.mnPoints ];
113cdf0e10cSrcweir 			memcpy( mpFlagAry, rImpPoly.mpFlagAry, rImpPoly.mnPoints );
114cdf0e10cSrcweir 		}
115cdf0e10cSrcweir 		else
116cdf0e10cSrcweir 			mpFlagAry = NULL;
117cdf0e10cSrcweir 	}
118cdf0e10cSrcweir 	else
119cdf0e10cSrcweir 	{
120cdf0e10cSrcweir 		mpPointAry = NULL;
121cdf0e10cSrcweir 		mpFlagAry = NULL;
122cdf0e10cSrcweir 	}
123cdf0e10cSrcweir 
124cdf0e10cSrcweir 	mnRefCount = 1;
125cdf0e10cSrcweir 	mnPoints   = rImpPoly.mnPoints;
126cdf0e10cSrcweir }
127cdf0e10cSrcweir 
128cdf0e10cSrcweir // -----------------------------------------------------------------------
129cdf0e10cSrcweir 
130cdf0e10cSrcweir ImplPolygon::ImplPolygon( sal_uInt16 nInitSize, const Point* pInitAry, const sal_uInt8* pInitFlags )
131cdf0e10cSrcweir {
132cdf0e10cSrcweir 	if ( nInitSize )
133cdf0e10cSrcweir 	{
134cdf0e10cSrcweir 		mpPointAry = (Point*)new char[(sal_uIntPtr)nInitSize*sizeof(Point)];
135cdf0e10cSrcweir 		memcpy( mpPointAry, pInitAry, (sal_uIntPtr)nInitSize*sizeof( Point ) );
136cdf0e10cSrcweir 
137cdf0e10cSrcweir 		if( pInitFlags )
138cdf0e10cSrcweir 		{
139cdf0e10cSrcweir 			mpFlagAry = new sal_uInt8[ nInitSize ];
140cdf0e10cSrcweir 			memcpy( mpFlagAry, pInitFlags, nInitSize );
141cdf0e10cSrcweir 		}
142cdf0e10cSrcweir 		else
143cdf0e10cSrcweir 			mpFlagAry = NULL;
144cdf0e10cSrcweir 	}
145cdf0e10cSrcweir 	else
146cdf0e10cSrcweir 	{
147cdf0e10cSrcweir 		mpPointAry = NULL;
148cdf0e10cSrcweir 		mpFlagAry  = NULL;
149cdf0e10cSrcweir 	}
150cdf0e10cSrcweir 
151cdf0e10cSrcweir 	mnRefCount = 1;
152cdf0e10cSrcweir 	mnPoints   = nInitSize;
153cdf0e10cSrcweir }
154cdf0e10cSrcweir 
155cdf0e10cSrcweir // -----------------------------------------------------------------------
156cdf0e10cSrcweir 
157cdf0e10cSrcweir ImplPolygon::~ImplPolygon()
158cdf0e10cSrcweir {
159cdf0e10cSrcweir 	if ( mpPointAry )
160cdf0e10cSrcweir 	{
161cdf0e10cSrcweir 		delete[] (char*) mpPointAry;
162cdf0e10cSrcweir 	}
163cdf0e10cSrcweir 
164cdf0e10cSrcweir 	if( mpFlagAry )
165cdf0e10cSrcweir 		delete[] mpFlagAry;
166cdf0e10cSrcweir }
167cdf0e10cSrcweir 
168cdf0e10cSrcweir // -----------------------------------------------------------------------
169cdf0e10cSrcweir 
170cdf0e10cSrcweir void ImplPolygon::ImplSetSize( sal_uInt16 nNewSize, sal_Bool bResize )
171cdf0e10cSrcweir {
172cdf0e10cSrcweir 	if( mnPoints == nNewSize )
173cdf0e10cSrcweir 		return;
174cdf0e10cSrcweir 
175cdf0e10cSrcweir 	Point* pNewAry;
176cdf0e10cSrcweir 
177cdf0e10cSrcweir 	if ( nNewSize )
178cdf0e10cSrcweir 	{
179cdf0e10cSrcweir 		pNewAry = (Point*)new char[(sal_uIntPtr)nNewSize*sizeof(Point)];
180cdf0e10cSrcweir 
181cdf0e10cSrcweir 		if ( bResize )
182cdf0e10cSrcweir 		{
183cdf0e10cSrcweir 			// Alte Punkte kopieren
184cdf0e10cSrcweir 			if ( mnPoints < nNewSize )
185cdf0e10cSrcweir 			{
186cdf0e10cSrcweir 				// Neue Punkte mit 0 initialisieren
187cdf0e10cSrcweir 				memset( pNewAry+mnPoints, 0, (sal_uIntPtr)(nNewSize-mnPoints)*sizeof(Point) );
188cdf0e10cSrcweir 				if ( mpPointAry )
189cdf0e10cSrcweir 					memcpy( pNewAry, mpPointAry, mnPoints*sizeof(Point) );
190cdf0e10cSrcweir 			}
191cdf0e10cSrcweir 			else
192cdf0e10cSrcweir 			{
193cdf0e10cSrcweir 				if ( mpPointAry )
194cdf0e10cSrcweir 					memcpy( pNewAry, mpPointAry, (sal_uIntPtr)nNewSize*sizeof(Point) );
195cdf0e10cSrcweir 			}
196cdf0e10cSrcweir 		}
197cdf0e10cSrcweir 	}
198cdf0e10cSrcweir 	else
199cdf0e10cSrcweir 		pNewAry = NULL;
200cdf0e10cSrcweir 
201cdf0e10cSrcweir 	if ( mpPointAry )
202cdf0e10cSrcweir 		delete[] (char*) mpPointAry;
203cdf0e10cSrcweir 
204cdf0e10cSrcweir 	// ggf. FlagArray beruecksichtigen
205cdf0e10cSrcweir 	if( mpFlagAry )
206cdf0e10cSrcweir 	{
207cdf0e10cSrcweir 		sal_uInt8* pNewFlagAry;
208cdf0e10cSrcweir 
209cdf0e10cSrcweir 		if( nNewSize )
210cdf0e10cSrcweir 		{
211cdf0e10cSrcweir 			pNewFlagAry = new sal_uInt8[ nNewSize ];
212cdf0e10cSrcweir 
213cdf0e10cSrcweir 			if( bResize )
214cdf0e10cSrcweir 			{
215cdf0e10cSrcweir 				// Alte Flags kopieren
216cdf0e10cSrcweir 				if ( mnPoints < nNewSize )
217cdf0e10cSrcweir 				{
218cdf0e10cSrcweir 					// Neue Punkte mit 0 initialisieren
219cdf0e10cSrcweir 					memset( pNewFlagAry+mnPoints, 0, nNewSize-mnPoints );
220cdf0e10cSrcweir 					memcpy( pNewFlagAry, mpFlagAry, mnPoints );
221cdf0e10cSrcweir 				}
222cdf0e10cSrcweir 				else
223cdf0e10cSrcweir 					memcpy( pNewFlagAry, mpFlagAry, nNewSize );
224cdf0e10cSrcweir 			}
225cdf0e10cSrcweir 		}
226cdf0e10cSrcweir 		else
227cdf0e10cSrcweir 			pNewFlagAry = NULL;
228cdf0e10cSrcweir 
229cdf0e10cSrcweir 		delete[] mpFlagAry;
230cdf0e10cSrcweir 		mpFlagAry  = pNewFlagAry;
231cdf0e10cSrcweir 	}
232cdf0e10cSrcweir 
233cdf0e10cSrcweir 	mpPointAry = pNewAry;
234cdf0e10cSrcweir 	mnPoints   = nNewSize;
235cdf0e10cSrcweir }
236cdf0e10cSrcweir 
237cdf0e10cSrcweir // -----------------------------------------------------------------------
238cdf0e10cSrcweir 
239cdf0e10cSrcweir void ImplPolygon::ImplSplit( sal_uInt16 nPos, sal_uInt16 nSpace, ImplPolygon* pInitPoly )
240cdf0e10cSrcweir {
241cdf0e10cSrcweir 	const sal_uIntPtr 	nSpaceSize = nSpace * sizeof( Point );
242cdf0e10cSrcweir 
243cdf0e10cSrcweir 	//Can't fit this in :-(, throw ?
244cdf0e10cSrcweir 	if (mnPoints + nSpace > USHRT_MAX)
245cdf0e10cSrcweir 		return;
246cdf0e10cSrcweir 
247cdf0e10cSrcweir 	const sal_uInt16	nNewSize = mnPoints + nSpace;
248cdf0e10cSrcweir 
249cdf0e10cSrcweir 	if( nPos >= mnPoints )
250cdf0e10cSrcweir 	{
251cdf0e10cSrcweir 		// Hinten anhaengen
252cdf0e10cSrcweir 		nPos = mnPoints;
253cdf0e10cSrcweir 		ImplSetSize( nNewSize, sal_True );
254cdf0e10cSrcweir 
255cdf0e10cSrcweir 		if( pInitPoly )
256cdf0e10cSrcweir 		{
257cdf0e10cSrcweir 			memcpy( mpPointAry + nPos, pInitPoly->mpPointAry, nSpaceSize );
258cdf0e10cSrcweir 
259cdf0e10cSrcweir 			if( pInitPoly->mpFlagAry )
260cdf0e10cSrcweir 				memcpy( mpFlagAry + nPos, pInitPoly->mpFlagAry, nSpace );
261cdf0e10cSrcweir 		}
262cdf0e10cSrcweir 	}
263cdf0e10cSrcweir 	else
264cdf0e10cSrcweir 	{
265cdf0e10cSrcweir 		// PointArray ist in diesem Zweig immer vorhanden
266cdf0e10cSrcweir 		const sal_uInt16	nSecPos = nPos + nSpace;
267cdf0e10cSrcweir 		const sal_uInt16	nRest = mnPoints - nPos;
268cdf0e10cSrcweir 
269cdf0e10cSrcweir 		Point* pNewAry = (Point*) new char[ (sal_uIntPtr) nNewSize * sizeof( Point ) ];
270cdf0e10cSrcweir 
271cdf0e10cSrcweir 		memcpy( pNewAry, mpPointAry, nPos * sizeof( Point ) );
272cdf0e10cSrcweir 
273cdf0e10cSrcweir 		if( pInitPoly )
274cdf0e10cSrcweir 			memcpy( pNewAry + nPos, pInitPoly->mpPointAry, nSpaceSize );
275cdf0e10cSrcweir 		else
276cdf0e10cSrcweir 			memset( pNewAry + nPos, 0, nSpaceSize );
277cdf0e10cSrcweir 
278cdf0e10cSrcweir 		memcpy( pNewAry + nSecPos, mpPointAry + nPos, nRest * sizeof( Point ) );
279cdf0e10cSrcweir 		delete[] (char*) mpPointAry;
280cdf0e10cSrcweir 
281cdf0e10cSrcweir 		// ggf. FlagArray beruecksichtigen
282cdf0e10cSrcweir 		if( mpFlagAry )
283cdf0e10cSrcweir 		{
284cdf0e10cSrcweir 			sal_uInt8* pNewFlagAry = new sal_uInt8[ nNewSize ];
285cdf0e10cSrcweir 
286cdf0e10cSrcweir 			memcpy( pNewFlagAry, mpFlagAry, nPos );
287cdf0e10cSrcweir 
288cdf0e10cSrcweir 			if( pInitPoly && pInitPoly->mpFlagAry )
289cdf0e10cSrcweir 				memcpy( pNewFlagAry + nPos, pInitPoly->mpFlagAry, nSpace );
290cdf0e10cSrcweir 			else
291cdf0e10cSrcweir 				memset( pNewFlagAry + nPos, 0, nSpace );
292cdf0e10cSrcweir 
293cdf0e10cSrcweir 			memcpy( pNewFlagAry + nSecPos, mpFlagAry + nPos, nRest );
294cdf0e10cSrcweir 			delete[] mpFlagAry;
295cdf0e10cSrcweir 			mpFlagAry = pNewFlagAry;
296cdf0e10cSrcweir 		}
297cdf0e10cSrcweir 
298cdf0e10cSrcweir 		mpPointAry = pNewAry;
299cdf0e10cSrcweir 		mnPoints   = nNewSize;
300cdf0e10cSrcweir 	}
301cdf0e10cSrcweir }
302cdf0e10cSrcweir 
303cdf0e10cSrcweir // -----------------------------------------------------------------------
304cdf0e10cSrcweir 
305cdf0e10cSrcweir void ImplPolygon::ImplRemove( sal_uInt16 nPos, sal_uInt16 nCount )
306cdf0e10cSrcweir {
307cdf0e10cSrcweir 	const sal_uInt16 nRemoveCount = Min( (sal_uInt16) ( mnPoints - nPos ), (sal_uInt16) nCount );
308cdf0e10cSrcweir 
309cdf0e10cSrcweir 	if( nRemoveCount )
310cdf0e10cSrcweir 	{
311cdf0e10cSrcweir 		const sal_uInt16	nNewSize = mnPoints - nRemoveCount;
312cdf0e10cSrcweir 		const sal_uInt16	nSecPos = nPos + nRemoveCount;
313cdf0e10cSrcweir 		const sal_uInt16	nRest = mnPoints - nSecPos;
314cdf0e10cSrcweir 
315cdf0e10cSrcweir 		Point* pNewAry = (Point*) new char[ (sal_uIntPtr) nNewSize * sizeof( Point ) ];
316cdf0e10cSrcweir 
317cdf0e10cSrcweir 		memcpy( pNewAry, mpPointAry, nPos * sizeof( Point ) );
318cdf0e10cSrcweir 		memcpy( pNewAry + nPos, mpPointAry + nSecPos, nRest * sizeof( Point ) );
319cdf0e10cSrcweir 
320cdf0e10cSrcweir 		delete[] (char*) mpPointAry;
321cdf0e10cSrcweir 
322cdf0e10cSrcweir 		// ggf. FlagArray beruecksichtigen
323cdf0e10cSrcweir 		if( mpFlagAry )
324cdf0e10cSrcweir 		{
325cdf0e10cSrcweir 			sal_uInt8* pNewFlagAry = new sal_uInt8[ nNewSize ];
326cdf0e10cSrcweir 
327cdf0e10cSrcweir 			memcpy( pNewFlagAry, mpFlagAry, nPos );
328cdf0e10cSrcweir 			memcpy( pNewFlagAry + nPos, mpFlagAry + nSecPos, nRest );
329cdf0e10cSrcweir 			delete[] mpFlagAry;
330cdf0e10cSrcweir 			mpFlagAry = pNewFlagAry;
331cdf0e10cSrcweir 		}
332cdf0e10cSrcweir 
333cdf0e10cSrcweir 		mpPointAry = pNewAry;
334cdf0e10cSrcweir 		mnPoints   = nNewSize;
335cdf0e10cSrcweir 	}
336cdf0e10cSrcweir }
337cdf0e10cSrcweir 
338cdf0e10cSrcweir // -----------------------------------------------------------------------
339cdf0e10cSrcweir 
340cdf0e10cSrcweir void ImplPolygon::ImplCreateFlagArray()
341cdf0e10cSrcweir {
342cdf0e10cSrcweir 	if( !mpFlagAry )
343cdf0e10cSrcweir 	{
344cdf0e10cSrcweir 		mpFlagAry = new sal_uInt8[ mnPoints ];
345cdf0e10cSrcweir 		memset( mpFlagAry, 0, mnPoints );
346cdf0e10cSrcweir 	}
347cdf0e10cSrcweir }
348cdf0e10cSrcweir 
349cdf0e10cSrcweir // =======================================================================
350cdf0e10cSrcweir 
351cdf0e10cSrcweir inline void Polygon::ImplMakeUnique()
352cdf0e10cSrcweir {
353cdf0e10cSrcweir 	// Falls noch andere Referenzen bestehen, dann kopieren
354cdf0e10cSrcweir 	if ( mpImplPolygon->mnRefCount != 1 )
355cdf0e10cSrcweir 	{
356cdf0e10cSrcweir 		if ( mpImplPolygon->mnRefCount )
357cdf0e10cSrcweir 			mpImplPolygon->mnRefCount--;
358cdf0e10cSrcweir 		mpImplPolygon = new ImplPolygon( *mpImplPolygon );
359cdf0e10cSrcweir 	}
360cdf0e10cSrcweir }
361cdf0e10cSrcweir 
362cdf0e10cSrcweir // -----------------------------------------------------------------------
363cdf0e10cSrcweir 
364cdf0e10cSrcweir inline double ImplGetAngle( const Point& rCenter, const Point& rPt )
365cdf0e10cSrcweir {
366cdf0e10cSrcweir 	const long nDX = rPt.X() - rCenter.X();
367cdf0e10cSrcweir 	return( atan2( -rPt.Y() + rCenter.Y(), ( ( nDX == 0L ) ? 0.000000001 : nDX ) ) );
368cdf0e10cSrcweir }
369cdf0e10cSrcweir 
370cdf0e10cSrcweir // -----------------------------------------------------------------------
371cdf0e10cSrcweir 
372cdf0e10cSrcweir Polygon::Polygon()
373cdf0e10cSrcweir {
374cdf0e10cSrcweir 	DBG_CTOR( Polygon, NULL );
375cdf0e10cSrcweir 	mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon);
376cdf0e10cSrcweir }
377cdf0e10cSrcweir 
378cdf0e10cSrcweir // -----------------------------------------------------------------------
379cdf0e10cSrcweir 
380cdf0e10cSrcweir Polygon::Polygon( sal_uInt16 nSize )
381cdf0e10cSrcweir {
382cdf0e10cSrcweir 	DBG_CTOR( Polygon, NULL );
383cdf0e10cSrcweir 
384cdf0e10cSrcweir 	if ( nSize )
385cdf0e10cSrcweir 		mpImplPolygon = new ImplPolygon( nSize );
386cdf0e10cSrcweir 	else
387cdf0e10cSrcweir 		mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon);
388cdf0e10cSrcweir }
389cdf0e10cSrcweir 
390cdf0e10cSrcweir // -----------------------------------------------------------------------
391cdf0e10cSrcweir 
392cdf0e10cSrcweir Polygon::Polygon( sal_uInt16 nPoints, const Point* pPtAry, const sal_uInt8* pFlagAry )
393cdf0e10cSrcweir {
394cdf0e10cSrcweir 	DBG_CTOR( Polygon, NULL );
395cdf0e10cSrcweir 
396cdf0e10cSrcweir 	if( nPoints )
397cdf0e10cSrcweir 		mpImplPolygon = new ImplPolygon( nPoints, pPtAry, pFlagAry );
398cdf0e10cSrcweir 	else
399cdf0e10cSrcweir 		mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon);
400cdf0e10cSrcweir }
401cdf0e10cSrcweir 
402cdf0e10cSrcweir // -----------------------------------------------------------------------
403cdf0e10cSrcweir 
404cdf0e10cSrcweir Polygon::Polygon( const Polygon& rPoly )
405cdf0e10cSrcweir {
406cdf0e10cSrcweir 	DBG_CTOR( Polygon, NULL );
407cdf0e10cSrcweir 	DBG_CHKOBJ( &rPoly, Polygon, NULL );
408cdf0e10cSrcweir 	DBG_ASSERT( rPoly.mpImplPolygon->mnRefCount < 0xFFFFFFFE, "Polygon: RefCount overflow" );
409cdf0e10cSrcweir 
410cdf0e10cSrcweir 	mpImplPolygon = rPoly.mpImplPolygon;
411cdf0e10cSrcweir 	if ( mpImplPolygon->mnRefCount )
412cdf0e10cSrcweir 		mpImplPolygon->mnRefCount++;
413cdf0e10cSrcweir }
414cdf0e10cSrcweir 
415cdf0e10cSrcweir // -----------------------------------------------------------------------
416cdf0e10cSrcweir 
417cdf0e10cSrcweir Polygon::Polygon( const Rectangle& rRect )
418cdf0e10cSrcweir {
419cdf0e10cSrcweir 	DBG_CTOR( Polygon, NULL );
420cdf0e10cSrcweir 
421cdf0e10cSrcweir 	if ( rRect.IsEmpty() )
422cdf0e10cSrcweir 		mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon);
423cdf0e10cSrcweir 	else
424cdf0e10cSrcweir 	{
425cdf0e10cSrcweir 		mpImplPolygon = new ImplPolygon( 5 );
426cdf0e10cSrcweir 		mpImplPolygon->mpPointAry[0] = rRect.TopLeft();
427cdf0e10cSrcweir 		mpImplPolygon->mpPointAry[1] = rRect.TopRight();
428cdf0e10cSrcweir 		mpImplPolygon->mpPointAry[2] = rRect.BottomRight();
429cdf0e10cSrcweir 		mpImplPolygon->mpPointAry[3] = rRect.BottomLeft();
430cdf0e10cSrcweir 		mpImplPolygon->mpPointAry[4] = rRect.TopLeft();
431cdf0e10cSrcweir 	}
432cdf0e10cSrcweir }
433cdf0e10cSrcweir 
434cdf0e10cSrcweir // -----------------------------------------------------------------------
435cdf0e10cSrcweir 
436cdf0e10cSrcweir Polygon::Polygon( const Rectangle& rRect, sal_uIntPtr nHorzRound, sal_uIntPtr nVertRound )
437cdf0e10cSrcweir {
438cdf0e10cSrcweir 	DBG_CTOR( Polygon, NULL );
439cdf0e10cSrcweir 
440cdf0e10cSrcweir 	if ( rRect.IsEmpty() )
441cdf0e10cSrcweir 		mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon);
442cdf0e10cSrcweir 	else
443cdf0e10cSrcweir 	{
444cdf0e10cSrcweir 		Rectangle aRect( rRect );
445cdf0e10cSrcweir 		aRect.Justify();			// SJ: i9140
446cdf0e10cSrcweir 
447cdf0e10cSrcweir 		nHorzRound = Min( nHorzRound, (sal_uIntPtr) labs( aRect.GetWidth() >> 1 ) );
448cdf0e10cSrcweir 		nVertRound = Min( nVertRound, (sal_uIntPtr) labs( aRect.GetHeight() >> 1 ) );
449cdf0e10cSrcweir 
450cdf0e10cSrcweir 		if( !nHorzRound && !nVertRound )
451cdf0e10cSrcweir 		{
452cdf0e10cSrcweir 			mpImplPolygon = new ImplPolygon( 5 );
453cdf0e10cSrcweir 			mpImplPolygon->mpPointAry[0] = aRect.TopLeft();
454cdf0e10cSrcweir 			mpImplPolygon->mpPointAry[1] = aRect.TopRight();
455cdf0e10cSrcweir 			mpImplPolygon->mpPointAry[2] = aRect.BottomRight();
456cdf0e10cSrcweir 			mpImplPolygon->mpPointAry[3] = aRect.BottomLeft();
457cdf0e10cSrcweir 			mpImplPolygon->mpPointAry[4] = aRect.TopLeft();
458cdf0e10cSrcweir 		}
459cdf0e10cSrcweir 		else
460cdf0e10cSrcweir 		{
461cdf0e10cSrcweir 			const Point		aTL( aRect.Left() + nHorzRound, aRect.Top() + nVertRound );
462cdf0e10cSrcweir 			const Point		aTR( aRect.Right() - nHorzRound, aRect.Top() + nVertRound );
463cdf0e10cSrcweir 			const Point		aBR( aRect.Right() - nHorzRound, aRect.Bottom() - nVertRound );
464cdf0e10cSrcweir 			const Point		aBL( aRect.Left() + nHorzRound, aRect.Bottom() - nVertRound );
465cdf0e10cSrcweir 			Polygon*		pEllipsePoly = new Polygon( Point(), nHorzRound, nVertRound );
466cdf0e10cSrcweir 			sal_uInt16			i, nEnd, nSize4 = pEllipsePoly->GetSize() >> 2;
467cdf0e10cSrcweir 
468cdf0e10cSrcweir 			mpImplPolygon = new ImplPolygon( pEllipsePoly->GetSize() + 1 );
469cdf0e10cSrcweir 
470cdf0e10cSrcweir 			const Point*	pSrcAry = pEllipsePoly->GetConstPointAry();
471cdf0e10cSrcweir 			Point*			pDstAry = mpImplPolygon->mpPointAry;
472cdf0e10cSrcweir 
473cdf0e10cSrcweir 			for( i = 0, nEnd = nSize4; i < nEnd; i++ )
474cdf0e10cSrcweir 				( pDstAry[ i ] = pSrcAry[ i ] ) += aTR;
475cdf0e10cSrcweir 
476cdf0e10cSrcweir 			for( nEnd = nEnd + nSize4; i < nEnd; i++ )
477cdf0e10cSrcweir 				( pDstAry[ i ] = pSrcAry[ i ] ) += aTL;
478cdf0e10cSrcweir 
479cdf0e10cSrcweir 			for( nEnd = nEnd + nSize4; i < nEnd; i++ )
480cdf0e10cSrcweir 				( pDstAry[ i ] = pSrcAry[ i ] ) += aBL;
481cdf0e10cSrcweir 
482cdf0e10cSrcweir 			for( nEnd = nEnd + nSize4; i < nEnd; i++ )
483cdf0e10cSrcweir 				( pDstAry[ i ] = pSrcAry[ i ] ) += aBR;
484cdf0e10cSrcweir 
485cdf0e10cSrcweir 			pDstAry[ nEnd ] = pDstAry[ 0 ];
486cdf0e10cSrcweir 			delete pEllipsePoly;
487cdf0e10cSrcweir 		}
488cdf0e10cSrcweir 	}
489cdf0e10cSrcweir }
490cdf0e10cSrcweir 
491cdf0e10cSrcweir // -----------------------------------------------------------------------
492cdf0e10cSrcweir 
493cdf0e10cSrcweir Polygon::Polygon( const Point& rCenter, long nRadX, long nRadY, sal_uInt16 nPoints )
494cdf0e10cSrcweir {
495cdf0e10cSrcweir 	DBG_CTOR( Polygon, NULL );
496cdf0e10cSrcweir 
497cdf0e10cSrcweir 	if( nRadX && nRadY )
498cdf0e10cSrcweir 	{
499cdf0e10cSrcweir 		// Default berechnen (abhaengig von Groesse)
500cdf0e10cSrcweir 		if( !nPoints )
501cdf0e10cSrcweir 		{
502cdf0e10cSrcweir 			nPoints = (sal_uInt16) ( F_PI * ( 1.5 * ( nRadX + nRadY ) -
503cdf0e10cSrcweir 								 sqrt( (double) labs( nRadX * nRadY ) ) ) );
504cdf0e10cSrcweir 
505cdf0e10cSrcweir 			nPoints = (sal_uInt16) MinMax( nPoints, 32, 256 );
506cdf0e10cSrcweir 
507cdf0e10cSrcweir 			if( ( nRadX > 32 ) && ( nRadY > 32 ) && ( nRadX + nRadY ) < 8192 )
508cdf0e10cSrcweir 				nPoints >>= 1;
509cdf0e10cSrcweir 		}
510cdf0e10cSrcweir 
511cdf0e10cSrcweir 		// Anzahl der Punkte auf durch 4 teilbare Zahl aufrunden
512cdf0e10cSrcweir 		mpImplPolygon = new ImplPolygon( nPoints = (nPoints + 3) & ~3 );
513cdf0e10cSrcweir 
514cdf0e10cSrcweir 		Point* pPt;
515cdf0e10cSrcweir 		sal_uInt16 i;
516cdf0e10cSrcweir 		sal_uInt16 nPoints2 = nPoints >> 1;
517cdf0e10cSrcweir 		sal_uInt16 nPoints4 = nPoints >> 2;
518cdf0e10cSrcweir 		double nAngle;
519cdf0e10cSrcweir 		double nAngleStep = F_PI2 / ( nPoints4 - 1 );
520cdf0e10cSrcweir 
521cdf0e10cSrcweir 		for( i=0, nAngle = 0.0; i < nPoints4; i++, nAngle += nAngleStep )
522cdf0e10cSrcweir 		{
523cdf0e10cSrcweir 			long nX = FRound( nRadX * cos( nAngle ) );
524cdf0e10cSrcweir 			long nY = FRound( -nRadY * sin( nAngle ) );
525cdf0e10cSrcweir 
526cdf0e10cSrcweir 			pPt = &(mpImplPolygon->mpPointAry[i]);
527cdf0e10cSrcweir 			pPt->X() =	nX + rCenter.X();
528cdf0e10cSrcweir 			pPt->Y() =	nY + rCenter.Y();
529cdf0e10cSrcweir 			pPt = &(mpImplPolygon->mpPointAry[nPoints2-i-1]);
530cdf0e10cSrcweir 			pPt->X() = -nX + rCenter.X();
531cdf0e10cSrcweir 			pPt->Y() =	nY + rCenter.Y();
532cdf0e10cSrcweir 			pPt = &(mpImplPolygon->mpPointAry[i+nPoints2]);
533cdf0e10cSrcweir 			pPt->X() = -nX + rCenter.X();
534cdf0e10cSrcweir 			pPt->Y() = -nY + rCenter.Y();
535cdf0e10cSrcweir 			pPt = &(mpImplPolygon->mpPointAry[nPoints-i-1]);
536cdf0e10cSrcweir 			pPt->X() =	nX + rCenter.X();
537cdf0e10cSrcweir 			pPt->Y() = -nY + rCenter.Y();
538cdf0e10cSrcweir 		}
539cdf0e10cSrcweir 	}
540cdf0e10cSrcweir 	else
541cdf0e10cSrcweir 		mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon);
542cdf0e10cSrcweir }
543cdf0e10cSrcweir 
544cdf0e10cSrcweir // -----------------------------------------------------------------------
545cdf0e10cSrcweir 
546cdf0e10cSrcweir Polygon::Polygon( const Rectangle& rBound,
547cdf0e10cSrcweir 				  const Point& rStart, const Point& rEnd, PolyStyle eStyle )
548cdf0e10cSrcweir {
549cdf0e10cSrcweir 	DBG_CTOR( Polygon, NULL );
550cdf0e10cSrcweir 
551cdf0e10cSrcweir 	const long	nWidth = rBound.GetWidth();
552cdf0e10cSrcweir 	const long	nHeight = rBound.GetHeight();
553cdf0e10cSrcweir 
554cdf0e10cSrcweir 	if( ( nWidth > 1 ) && ( nHeight > 1 ) )
555cdf0e10cSrcweir 	{
556cdf0e10cSrcweir 		const Point aCenter( rBound.Center() );
557cdf0e10cSrcweir 		const long	nRadX = aCenter.X() - rBound.Left();
558cdf0e10cSrcweir 		const long	nRadY = aCenter.Y() - rBound.Top();
559cdf0e10cSrcweir 		sal_uInt16		nPoints;
560cdf0e10cSrcweir 
561cdf0e10cSrcweir 		nPoints = (sal_uInt16) ( F_PI * ( 1.5 * ( nRadX + nRadY ) -
562cdf0e10cSrcweir 							 sqrt( (double) labs( nRadX * nRadY ) ) ) );
563cdf0e10cSrcweir 
564cdf0e10cSrcweir 		nPoints = (sal_uInt16) MinMax( nPoints, 32, 256 );
565cdf0e10cSrcweir 
566cdf0e10cSrcweir 		if( ( nRadX > 32 ) && ( nRadY > 32 ) && ( nRadX + nRadY ) < 8192 )
567cdf0e10cSrcweir 			nPoints >>= 1;
568cdf0e10cSrcweir 
569cdf0e10cSrcweir 		// Winkel berechnen
570cdf0e10cSrcweir 		const double	fRadX = nRadX;
571cdf0e10cSrcweir 		const double	fRadY = nRadY;
572cdf0e10cSrcweir 		const double	fCenterX = aCenter.X();
573cdf0e10cSrcweir 		const double	fCenterY = aCenter.Y();
574cdf0e10cSrcweir 		double			fStart = ImplGetAngle( aCenter, rStart );
575cdf0e10cSrcweir 		double			fEnd = ImplGetAngle( aCenter, rEnd );
576cdf0e10cSrcweir 		double			fDiff = fEnd - fStart;
577cdf0e10cSrcweir 		double			fStep;
578cdf0e10cSrcweir 		sal_uInt16			nStart;
579cdf0e10cSrcweir 		sal_uInt16			nEnd;
580cdf0e10cSrcweir 
581cdf0e10cSrcweir 		if( fDiff < 0. )
582cdf0e10cSrcweir 			fDiff += F_2PI;
583cdf0e10cSrcweir 
584cdf0e10cSrcweir 		// Punktanzahl proportional verkleinern ( fDiff / (2PI) );
585cdf0e10cSrcweir 		// ist eingentlich nur fuer einen Kreis richtig; wir
586cdf0e10cSrcweir 		// machen es hier aber trotzdem
587cdf0e10cSrcweir 		nPoints = Max( (sal_uInt16) ( ( fDiff * 0.1591549 ) * nPoints ), (sal_uInt16) 16 );
588cdf0e10cSrcweir 		fStep = fDiff / ( nPoints - 1 );
589cdf0e10cSrcweir 
590cdf0e10cSrcweir 		if( POLY_PIE == eStyle )
591cdf0e10cSrcweir 		{
592cdf0e10cSrcweir 			const Point aCenter2( FRound( fCenterX ), FRound( fCenterY ) );
593cdf0e10cSrcweir 
594cdf0e10cSrcweir 			nStart = 1;
595cdf0e10cSrcweir 			nEnd = nPoints + 1;
596cdf0e10cSrcweir 			mpImplPolygon = new ImplPolygon( nPoints + 2 );
597cdf0e10cSrcweir 			mpImplPolygon->mpPointAry[ 0 ] = aCenter2;
598cdf0e10cSrcweir 			mpImplPolygon->mpPointAry[ nEnd ] = aCenter2;
599cdf0e10cSrcweir 		}
600cdf0e10cSrcweir 		else
601cdf0e10cSrcweir 		{
602cdf0e10cSrcweir 			mpImplPolygon = new ImplPolygon( ( POLY_CHORD == eStyle ) ? ( nPoints + 1 ) : nPoints );
603cdf0e10cSrcweir 			nStart = 0;
604cdf0e10cSrcweir 			nEnd = nPoints;
605cdf0e10cSrcweir 		}
606cdf0e10cSrcweir 
607cdf0e10cSrcweir 		for(; nStart < nEnd; nStart++, fStart += fStep )
608cdf0e10cSrcweir 		{
609cdf0e10cSrcweir 			Point& rPt = mpImplPolygon->mpPointAry[ nStart ];
610cdf0e10cSrcweir 
611cdf0e10cSrcweir 			rPt.X() = FRound( fCenterX + fRadX * cos( fStart ) );
612cdf0e10cSrcweir 			rPt.Y() = FRound( fCenterY - fRadY * sin( fStart ) );
613cdf0e10cSrcweir 		}
614cdf0e10cSrcweir 
615cdf0e10cSrcweir 		if( POLY_CHORD == eStyle )
616cdf0e10cSrcweir 			mpImplPolygon->mpPointAry[ nPoints ] = mpImplPolygon->mpPointAry[ 0 ];
617cdf0e10cSrcweir 	}
618cdf0e10cSrcweir 	else
619cdf0e10cSrcweir 		mpImplPolygon = (ImplPolygon*) &aStaticImplPolygon;
620cdf0e10cSrcweir }
621cdf0e10cSrcweir 
622cdf0e10cSrcweir // -----------------------------------------------------------------------
623cdf0e10cSrcweir 
624cdf0e10cSrcweir Polygon::Polygon( const Point& rBezPt1, const Point& rCtrlPt1,
625cdf0e10cSrcweir 				  const Point& rBezPt2, const Point& rCtrlPt2,
626cdf0e10cSrcweir 				  sal_uInt16 nPoints )
627cdf0e10cSrcweir {
628cdf0e10cSrcweir 	DBG_CTOR( Polygon, NULL );
629cdf0e10cSrcweir 
630cdf0e10cSrcweir 	nPoints = ( 0 == nPoints ) ? 25 : ( ( nPoints < 2 ) ? 2 : nPoints );
631cdf0e10cSrcweir 
632cdf0e10cSrcweir 	const double	fInc = 1.0 / ( nPoints - 1 );
633cdf0e10cSrcweir 	double			fK_1 = 0.0, fK1_1 = 1.0;
634cdf0e10cSrcweir 	double			fK_2, fK_3, fK1_2, fK1_3, fK12, fK21;
635cdf0e10cSrcweir 	const double	fX0 = rBezPt1.X();
636cdf0e10cSrcweir 	const double	fY0 = rBezPt1.Y();
637cdf0e10cSrcweir 	const double	fX1 = 3.0 * rCtrlPt1.X();
638cdf0e10cSrcweir 	const double	fY1 = 3.0 * rCtrlPt1.Y();
639cdf0e10cSrcweir 	const double	fX2 = 3.0 * rCtrlPt2.X();;
640cdf0e10cSrcweir 	const double	fY2 = 3.0 * rCtrlPt2.Y();;
641cdf0e10cSrcweir 	const double	fX3 = rBezPt2.X();
642cdf0e10cSrcweir 	const double	fY3 = rBezPt2.Y();
643cdf0e10cSrcweir 
644cdf0e10cSrcweir 	mpImplPolygon = new ImplPolygon( nPoints );
645cdf0e10cSrcweir 
646cdf0e10cSrcweir 	for( sal_uInt16 i = 0; i < nPoints; i++, fK_1 += fInc, fK1_1 -= fInc )
647cdf0e10cSrcweir 	{
648cdf0e10cSrcweir 		Point& rPt = mpImplPolygon->mpPointAry[ i ];
649cdf0e10cSrcweir 
650cdf0e10cSrcweir 		fK_2 = fK_1, fK_3 = ( fK_2 *= fK_1 ), fK_3 *= fK_1;
651cdf0e10cSrcweir 		fK1_2 = fK1_1, fK1_3 = ( fK1_2 *= fK1_1 ), fK1_3 *= fK1_1;
652cdf0e10cSrcweir 		fK12 = fK_1 * fK1_2, fK21 = fK_2 * fK1_1;
653cdf0e10cSrcweir 
654cdf0e10cSrcweir 		rPt.X() = FRound( fK1_3 * fX0 + fK12 * fX1 + fK21 * fX2 + fK_3 * fX3 );
655cdf0e10cSrcweir 		rPt.Y() = FRound( fK1_3 * fY0 + fK12 * fY1 + fK21 * fY2 + fK_3 * fY3 );
656cdf0e10cSrcweir 	}
657cdf0e10cSrcweir }
658cdf0e10cSrcweir 
659cdf0e10cSrcweir // -----------------------------------------------------------------------
660cdf0e10cSrcweir 
661cdf0e10cSrcweir Polygon::~Polygon()
662cdf0e10cSrcweir {
663cdf0e10cSrcweir 	DBG_DTOR( Polygon, NULL );
664cdf0e10cSrcweir 
665cdf0e10cSrcweir 	// Wenn es keine statischen ImpDaten sind, dann loeschen, wenn es
666cdf0e10cSrcweir 	// die letzte Referenz ist, sonst Referenzcounter decrementieren
667cdf0e10cSrcweir 	if ( mpImplPolygon->mnRefCount )
668cdf0e10cSrcweir 	{
669cdf0e10cSrcweir 		if ( mpImplPolygon->mnRefCount > 1 )
670cdf0e10cSrcweir 			mpImplPolygon->mnRefCount--;
671cdf0e10cSrcweir 		else
672cdf0e10cSrcweir 			delete mpImplPolygon;
673cdf0e10cSrcweir 	}
674cdf0e10cSrcweir }
675cdf0e10cSrcweir 
676cdf0e10cSrcweir // -----------------------------------------------------------------------
677cdf0e10cSrcweir 
678cdf0e10cSrcweir Point* Polygon::ImplGetPointAry()
679cdf0e10cSrcweir {
680cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
681cdf0e10cSrcweir 
682cdf0e10cSrcweir 	ImplMakeUnique();
683cdf0e10cSrcweir 	return (Point*)mpImplPolygon->mpPointAry;
684cdf0e10cSrcweir }
685cdf0e10cSrcweir 
686cdf0e10cSrcweir // -----------------------------------------------------------------------
687cdf0e10cSrcweir 
688cdf0e10cSrcweir sal_uInt8* Polygon::ImplGetFlagAry()
689cdf0e10cSrcweir {
690cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
691cdf0e10cSrcweir 
692cdf0e10cSrcweir 	ImplMakeUnique();
693cdf0e10cSrcweir 	mpImplPolygon->ImplCreateFlagArray();
694cdf0e10cSrcweir 	return mpImplPolygon->mpFlagAry;
695cdf0e10cSrcweir }
696cdf0e10cSrcweir 
697cdf0e10cSrcweir // -----------------------------------------------------------------------
698cdf0e10cSrcweir 
699cdf0e10cSrcweir const Point* Polygon::GetConstPointAry() const
700cdf0e10cSrcweir {
701cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
702cdf0e10cSrcweir 	return (Point*)mpImplPolygon->mpPointAry;
703cdf0e10cSrcweir }
704cdf0e10cSrcweir 
705cdf0e10cSrcweir // -----------------------------------------------------------------------
706cdf0e10cSrcweir 
707cdf0e10cSrcweir const sal_uInt8* Polygon::GetConstFlagAry() const
708cdf0e10cSrcweir {
709cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
710cdf0e10cSrcweir 	return mpImplPolygon->mpFlagAry;
711cdf0e10cSrcweir }
712cdf0e10cSrcweir 
713cdf0e10cSrcweir // -----------------------------------------------------------------------
714cdf0e10cSrcweir 
715cdf0e10cSrcweir void Polygon::SetPoint( const Point& rPt, sal_uInt16 nPos )
716cdf0e10cSrcweir {
717cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
718cdf0e10cSrcweir 	DBG_ASSERT( nPos < mpImplPolygon->mnPoints,
719cdf0e10cSrcweir 				"Polygon::SetPoint(): nPos >= nPoints" );
720cdf0e10cSrcweir 
721cdf0e10cSrcweir 	ImplMakeUnique();
722cdf0e10cSrcweir 	mpImplPolygon->mpPointAry[nPos] = rPt;
723cdf0e10cSrcweir }
724cdf0e10cSrcweir 
725cdf0e10cSrcweir // -----------------------------------------------------------------------
726cdf0e10cSrcweir 
727cdf0e10cSrcweir void Polygon::SetFlags( sal_uInt16 nPos, PolyFlags eFlags )
728cdf0e10cSrcweir {
729cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
730cdf0e10cSrcweir 	DBG_ASSERT( nPos < mpImplPolygon->mnPoints,
731cdf0e10cSrcweir 				"Polygon::SetFlags(): nPos >= nPoints" );
732cdf0e10cSrcweir 
733cdf0e10cSrcweir 	// we do only want to create the flag array if there
734cdf0e10cSrcweir 	// is at least one flag different to POLY_NORMAL
735cdf0e10cSrcweir 	if ( mpImplPolygon || ( eFlags != POLY_NORMAL ) )
736cdf0e10cSrcweir 	{
737cdf0e10cSrcweir 		ImplMakeUnique();
738cdf0e10cSrcweir 		mpImplPolygon->ImplCreateFlagArray();
739cdf0e10cSrcweir 		mpImplPolygon->mpFlagAry[ nPos ] = (sal_uInt8) eFlags;
740cdf0e10cSrcweir 	}
741cdf0e10cSrcweir }
742cdf0e10cSrcweir 
743cdf0e10cSrcweir // -----------------------------------------------------------------------
744cdf0e10cSrcweir 
745cdf0e10cSrcweir const Point& Polygon::GetPoint( sal_uInt16 nPos ) const
746cdf0e10cSrcweir {
747cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
748cdf0e10cSrcweir 	DBG_ASSERT( nPos < mpImplPolygon->mnPoints,
749cdf0e10cSrcweir 				"Polygon::GetPoint(): nPos >= nPoints" );
750cdf0e10cSrcweir 
751cdf0e10cSrcweir 	return mpImplPolygon->mpPointAry[nPos];
752cdf0e10cSrcweir }
753cdf0e10cSrcweir 
754cdf0e10cSrcweir // -----------------------------------------------------------------------
755cdf0e10cSrcweir 
756cdf0e10cSrcweir PolyFlags Polygon::GetFlags( sal_uInt16 nPos ) const
757cdf0e10cSrcweir {
758cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
759cdf0e10cSrcweir 	DBG_ASSERT( nPos < mpImplPolygon->mnPoints,
760cdf0e10cSrcweir 				"Polygon::GetFlags(): nPos >= nPoints" );
761cdf0e10cSrcweir 	return( mpImplPolygon->mpFlagAry ?
762cdf0e10cSrcweir 			(PolyFlags) mpImplPolygon->mpFlagAry[ nPos ] :
763cdf0e10cSrcweir 			POLY_NORMAL );
764cdf0e10cSrcweir }
765cdf0e10cSrcweir 
766cdf0e10cSrcweir // -----------------------------------------------------------------------
767cdf0e10cSrcweir 
768cdf0e10cSrcweir sal_Bool Polygon::HasFlags() const
769cdf0e10cSrcweir {
770cdf0e10cSrcweir 	return mpImplPolygon->mpFlagAry != NULL;
771cdf0e10cSrcweir }
772cdf0e10cSrcweir 
773cdf0e10cSrcweir // -----------------------------------------------------------------------
774cdf0e10cSrcweir 
775cdf0e10cSrcweir sal_Bool Polygon::IsControl(sal_uInt16 nPos) const
776cdf0e10cSrcweir {
777cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
778cdf0e10cSrcweir 	DBG_ASSERT( nPos < mpImplPolygon->mnPoints,
779cdf0e10cSrcweir 				"Polygon::GetFlags(): nPos >= nPoints" );
780cdf0e10cSrcweir 	PolyFlags eFlags = mpImplPolygon->mpFlagAry ?
781cdf0e10cSrcweir 					   (PolyFlags) mpImplPolygon->mpFlagAry[ nPos ] : POLY_NORMAL;
782cdf0e10cSrcweir 
783cdf0e10cSrcweir 	return( POLY_CONTROL == eFlags );
784cdf0e10cSrcweir }
785cdf0e10cSrcweir 
786cdf0e10cSrcweir // -----------------------------------------------------------------------
787cdf0e10cSrcweir 
788cdf0e10cSrcweir sal_Bool Polygon::IsSmooth(sal_uInt16 nPos) const
789cdf0e10cSrcweir {
790cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
791cdf0e10cSrcweir 	DBG_ASSERT( nPos < mpImplPolygon->mnPoints,
792cdf0e10cSrcweir 				"Polygon::GetFlags(): nPos >= nPoints" );
793cdf0e10cSrcweir 	PolyFlags eFlags = mpImplPolygon->mpFlagAry ?
794cdf0e10cSrcweir 					   (PolyFlags) mpImplPolygon->mpFlagAry[ nPos ] : POLY_NORMAL;
795cdf0e10cSrcweir 
796cdf0e10cSrcweir 	return( ( POLY_SMOOTH == eFlags ) || ( POLY_SYMMTR == eFlags ) );
797cdf0e10cSrcweir }
798cdf0e10cSrcweir 
799cdf0e10cSrcweir // -----------------------------------------------------------------------
800cdf0e10cSrcweir 
801cdf0e10cSrcweir sal_Bool Polygon::IsRect() const
802cdf0e10cSrcweir {
803cdf0e10cSrcweir 	sal_Bool bIsRect = sal_False;
804cdf0e10cSrcweir 	if ( mpImplPolygon->mpFlagAry == NULL )
805cdf0e10cSrcweir 	{
806cdf0e10cSrcweir 		if ( ( ( mpImplPolygon->mnPoints == 5 ) && ( mpImplPolygon->mpPointAry[ 0 ] == mpImplPolygon->mpPointAry[ 4 ] ) ) ||
807cdf0e10cSrcweir 				( mpImplPolygon->mnPoints == 4 ) )
808cdf0e10cSrcweir 		{
809cdf0e10cSrcweir 			if ( ( mpImplPolygon->mpPointAry[ 0 ].X() == mpImplPolygon->mpPointAry[ 3 ].X() ) &&
810cdf0e10cSrcweir 					( mpImplPolygon->mpPointAry[ 0 ].Y() == mpImplPolygon->mpPointAry[ 1 ].Y() ) &&
811cdf0e10cSrcweir 						( mpImplPolygon->mpPointAry[ 1 ].X() == mpImplPolygon->mpPointAry[ 2 ].X() ) &&
812cdf0e10cSrcweir 							( mpImplPolygon->mpPointAry[ 2 ].Y() == mpImplPolygon->mpPointAry[ 3 ].Y() ) )
813cdf0e10cSrcweir 				bIsRect = sal_True;
814cdf0e10cSrcweir 		}
815cdf0e10cSrcweir 	}
816cdf0e10cSrcweir 	return bIsRect;
817cdf0e10cSrcweir }
818cdf0e10cSrcweir 
819cdf0e10cSrcweir // -----------------------------------------------------------------------
820cdf0e10cSrcweir 
821cdf0e10cSrcweir void Polygon::SetSize( sal_uInt16 nNewSize )
822cdf0e10cSrcweir {
823cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
824cdf0e10cSrcweir 
825cdf0e10cSrcweir 	if( nNewSize != mpImplPolygon->mnPoints )
826cdf0e10cSrcweir 	{
827cdf0e10cSrcweir 		ImplMakeUnique();
828cdf0e10cSrcweir 		mpImplPolygon->ImplSetSize( nNewSize );
829cdf0e10cSrcweir 	}
830cdf0e10cSrcweir }
831cdf0e10cSrcweir 
832cdf0e10cSrcweir // -----------------------------------------------------------------------
833cdf0e10cSrcweir 
834cdf0e10cSrcweir sal_uInt16 Polygon::GetSize() const
835cdf0e10cSrcweir {
836cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
837cdf0e10cSrcweir 
838cdf0e10cSrcweir 	return mpImplPolygon->mnPoints;
839cdf0e10cSrcweir }
840cdf0e10cSrcweir 
841cdf0e10cSrcweir // -----------------------------------------------------------------------
842cdf0e10cSrcweir 
843cdf0e10cSrcweir void Polygon::Clear()
844cdf0e10cSrcweir {
845cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
846cdf0e10cSrcweir 
847cdf0e10cSrcweir 	if ( mpImplPolygon->mnRefCount )
848cdf0e10cSrcweir 	{
849cdf0e10cSrcweir 		if ( mpImplPolygon->mnRefCount > 1 )
850cdf0e10cSrcweir 			mpImplPolygon->mnRefCount--;
851cdf0e10cSrcweir 		else
852cdf0e10cSrcweir 			delete mpImplPolygon;
853cdf0e10cSrcweir 	}
854cdf0e10cSrcweir 
855cdf0e10cSrcweir 	mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon);
856cdf0e10cSrcweir }
857cdf0e10cSrcweir 
858cdf0e10cSrcweir // -----------------------------------------------------------------------
859cdf0e10cSrcweir 
860cdf0e10cSrcweir double Polygon::CalcDistance( sal_uInt16 nP1, sal_uInt16 nP2 )
861cdf0e10cSrcweir {
862cdf0e10cSrcweir 	DBG_ASSERT( nP1 < mpImplPolygon->mnPoints,
863cdf0e10cSrcweir 				"Polygon::CalcDistance(): nPos1 >= nPoints" );
864cdf0e10cSrcweir 	DBG_ASSERT( nP2 < mpImplPolygon->mnPoints,
865cdf0e10cSrcweir 				"Polygon::CalcDistance(): nPos2 >= nPoints" );
866cdf0e10cSrcweir 
867cdf0e10cSrcweir 	const Point& rP1 = mpImplPolygon->mpPointAry[ nP1 ];
868cdf0e10cSrcweir 	const Point& rP2 = mpImplPolygon->mpPointAry[ nP2 ];
869cdf0e10cSrcweir 	const double fDx = rP2.X() - rP1.X();
870cdf0e10cSrcweir 	const double fDy = rP2.Y() - rP1.Y();
871cdf0e10cSrcweir 
872cdf0e10cSrcweir 	return sqrt( fDx * fDx + fDy * fDy );
873cdf0e10cSrcweir }
874cdf0e10cSrcweir 
875cdf0e10cSrcweir // -----------------------------------------------------------------------
876cdf0e10cSrcweir 
877cdf0e10cSrcweir void Polygon::Optimize( sal_uIntPtr nOptimizeFlags, const PolyOptimizeData* pData )
878cdf0e10cSrcweir {
879cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
880cdf0e10cSrcweir 	DBG_ASSERT( !mpImplPolygon->mpFlagAry, "Optimizing could fail with beziers!" );
881cdf0e10cSrcweir 
882cdf0e10cSrcweir 	sal_uInt16 nSize = mpImplPolygon->mnPoints;
883cdf0e10cSrcweir 
884cdf0e10cSrcweir 	if( nOptimizeFlags && nSize )
885cdf0e10cSrcweir 	{
886cdf0e10cSrcweir 		if( nOptimizeFlags & POLY_OPTIMIZE_EDGES )
887cdf0e10cSrcweir 		{
888cdf0e10cSrcweir 			const Rectangle	aBound( GetBoundRect() );
889cdf0e10cSrcweir 			const double	fArea = ( aBound.GetWidth() + aBound.GetHeight() ) * 0.5;
890cdf0e10cSrcweir 			const sal_uInt16	nPercent = pData ? pData->GetPercentValue() : 50;
891cdf0e10cSrcweir 
892cdf0e10cSrcweir 			Optimize( POLY_OPTIMIZE_NO_SAME );
893cdf0e10cSrcweir 			ImplReduceEdges( *this, fArea, nPercent );
894cdf0e10cSrcweir 		}
895cdf0e10cSrcweir 		else if( nOptimizeFlags & ( POLY_OPTIMIZE_REDUCE | POLY_OPTIMIZE_NO_SAME ) )
896cdf0e10cSrcweir 		{
897cdf0e10cSrcweir 			Polygon			aNewPoly;
898cdf0e10cSrcweir 			const Point&	rFirst = mpImplPolygon->mpPointAry[ 0 ];
899cdf0e10cSrcweir 			sal_uIntPtr			nReduce;
900cdf0e10cSrcweir 
901cdf0e10cSrcweir 			if( nOptimizeFlags & ( POLY_OPTIMIZE_REDUCE ) )
902cdf0e10cSrcweir 				nReduce = pData ? pData->GetAbsValue() : 4UL;
903cdf0e10cSrcweir 			else
904cdf0e10cSrcweir 				nReduce = 0UL;
905cdf0e10cSrcweir 
906cdf0e10cSrcweir 			while( nSize && ( mpImplPolygon->mpPointAry[ nSize - 1 ] == rFirst ) )
907cdf0e10cSrcweir 				nSize--;
908cdf0e10cSrcweir 
909cdf0e10cSrcweir 			if( nSize > 1 )
910cdf0e10cSrcweir 			{
911cdf0e10cSrcweir 				sal_uInt16 nLast = 0, nNewCount = 1;
912cdf0e10cSrcweir 
913cdf0e10cSrcweir 				aNewPoly.SetSize( nSize );
914cdf0e10cSrcweir 				aNewPoly[ 0 ] = rFirst;
915cdf0e10cSrcweir 
916cdf0e10cSrcweir 				for( sal_uInt16 i = 1; i < nSize; i++ )
917cdf0e10cSrcweir 				{
918cdf0e10cSrcweir 					if( ( mpImplPolygon->mpPointAry[ i ] != mpImplPolygon->mpPointAry[ nLast ] ) &&
919cdf0e10cSrcweir 						( !nReduce || ( nReduce < (sal_uIntPtr) FRound( CalcDistance( nLast, i ) ) ) ) )
920cdf0e10cSrcweir 					{
921cdf0e10cSrcweir 						aNewPoly[ nNewCount++ ] = mpImplPolygon->mpPointAry[ nLast = i ];
922cdf0e10cSrcweir 					}
923cdf0e10cSrcweir 				}
924cdf0e10cSrcweir 
925cdf0e10cSrcweir 				if( nNewCount == 1 )
926cdf0e10cSrcweir 					aNewPoly.Clear();
927cdf0e10cSrcweir 				else
928cdf0e10cSrcweir 					aNewPoly.SetSize( nNewCount );
929cdf0e10cSrcweir 			}
930cdf0e10cSrcweir 
931cdf0e10cSrcweir 			*this = aNewPoly;
932cdf0e10cSrcweir 		}
933cdf0e10cSrcweir 
934cdf0e10cSrcweir 		nSize = mpImplPolygon->mnPoints;
935cdf0e10cSrcweir 
936cdf0e10cSrcweir 		if( nSize > 1 )
937cdf0e10cSrcweir 		{
938cdf0e10cSrcweir 			if( ( nOptimizeFlags & POLY_OPTIMIZE_CLOSE ) &&
939cdf0e10cSrcweir 				( mpImplPolygon->mpPointAry[ 0 ] != mpImplPolygon->mpPointAry[ nSize - 1 ] ) )
940cdf0e10cSrcweir 			{
941cdf0e10cSrcweir 				SetSize( mpImplPolygon->mnPoints + 1 );
942cdf0e10cSrcweir 				mpImplPolygon->mpPointAry[ mpImplPolygon->mnPoints - 1 ] = mpImplPolygon->mpPointAry[ 0 ];
943cdf0e10cSrcweir 			}
944cdf0e10cSrcweir 			else if( ( nOptimizeFlags & POLY_OPTIMIZE_OPEN ) &&
945cdf0e10cSrcweir 					 ( mpImplPolygon->mpPointAry[ 0 ] == mpImplPolygon->mpPointAry[ nSize - 1 ] ) )
946cdf0e10cSrcweir 			{
947cdf0e10cSrcweir 				const Point& rFirst = mpImplPolygon->mpPointAry[ 0 ];
948cdf0e10cSrcweir 
949cdf0e10cSrcweir 				while( nSize && ( mpImplPolygon->mpPointAry[ nSize - 1 ] == rFirst ) )
950cdf0e10cSrcweir 					nSize--;
951cdf0e10cSrcweir 
952cdf0e10cSrcweir 				SetSize( nSize );
953cdf0e10cSrcweir 			}
954cdf0e10cSrcweir 		}
955cdf0e10cSrcweir 	}
956cdf0e10cSrcweir }
957cdf0e10cSrcweir 
958cdf0e10cSrcweir // =======================================================================
959cdf0e10cSrcweir 
960cdf0e10cSrcweir /* Recursively subdivide cubic bezier curve via deCasteljau.
961cdf0e10cSrcweir 
962cdf0e10cSrcweir    @param rPointIter
963cdf0e10cSrcweir    Output iterator, where the subdivided polylines are written to.
964cdf0e10cSrcweir 
965cdf0e10cSrcweir    @param d
966cdf0e10cSrcweir    Squared difference of curve to a straight line
967cdf0e10cSrcweir 
968cdf0e10cSrcweir    @param P*
969cdf0e10cSrcweir    Exactly four points, interpreted as support and control points of
970cdf0e10cSrcweir    a cubic bezier curve. Must be in device coordinates, since stop
971cdf0e10cSrcweir    criterion is based on the following assumption: the device has a
972cdf0e10cSrcweir    finite resolution, it is thus sufficient to stop subdivision if the
973cdf0e10cSrcweir    curve does not deviate more than one pixel from a straight line.
974cdf0e10cSrcweir 
975cdf0e10cSrcweir */
976cdf0e10cSrcweir static void ImplAdaptiveSubdivide( ::std::back_insert_iterator< ::std::vector< Point > >& rPointIter,
977cdf0e10cSrcweir                                    const double old_d2,
978cdf0e10cSrcweir                                    int recursionDepth,
979cdf0e10cSrcweir                                    const double d2,
980cdf0e10cSrcweir                                    const double P1x, const double P1y,
981cdf0e10cSrcweir                                    const double P2x, const double P2y,
982cdf0e10cSrcweir                                    const double P3x, const double P3y,
983cdf0e10cSrcweir                                    const double P4x, const double P4y )
984cdf0e10cSrcweir {
985cdf0e10cSrcweir     // Hard limit on recursion depth, empiric number.
986cdf0e10cSrcweir     enum {maxRecursionDepth=128};
987cdf0e10cSrcweir 
988cdf0e10cSrcweir     // Perform bezier flatness test (lecture notes from R. Schaback,
989cdf0e10cSrcweir     // Mathematics of Computer-Aided Design, Uni Goettingen, 2000)
990cdf0e10cSrcweir     //
991cdf0e10cSrcweir     // ||P(t) - L(t)|| <= max     ||b_j - b_0 - j/n(b_n - b_0)||
992cdf0e10cSrcweir     //                    0<=j<=n
993cdf0e10cSrcweir     //
994cdf0e10cSrcweir     // What is calculated here is an upper bound to the distance from
995cdf0e10cSrcweir     // a line through b_0 and b_3 (P1 and P4 in our notation) and the
996cdf0e10cSrcweir     // curve. We can drop 0 and n from the running indices, since the
997cdf0e10cSrcweir     // argument of max becomes zero for those cases.
998cdf0e10cSrcweir     const double fJ1x( P2x - P1x - 1.0/3.0*(P4x - P1x) );
999cdf0e10cSrcweir     const double fJ1y( P2y - P1y - 1.0/3.0*(P4y - P1y) );
1000cdf0e10cSrcweir     const double fJ2x( P3x - P1x - 2.0/3.0*(P4x - P1x) );
1001cdf0e10cSrcweir     const double fJ2y( P3y - P1y - 2.0/3.0*(P4y - P1y) );
1002cdf0e10cSrcweir     const double distance2( ::std::max( fJ1x*fJ1x + fJ1y*fJ1y,
1003cdf0e10cSrcweir                                         fJ2x*fJ2x + fJ2y*fJ2y) );
1004cdf0e10cSrcweir 
1005cdf0e10cSrcweir     // stop if error measure does not improve anymore. This is a
1006cdf0e10cSrcweir     // safety guard against floating point inaccuracies.
1007cdf0e10cSrcweir     // stop at recursion level 128. This is a safety guard against
1008cdf0e10cSrcweir     // floating point inaccuracies.
1009cdf0e10cSrcweir     // stop if distance from line is guaranteed to be bounded by d
1010cdf0e10cSrcweir     if( old_d2 > d2 &&
1011cdf0e10cSrcweir         recursionDepth < maxRecursionDepth &&
1012cdf0e10cSrcweir         distance2 >= d2 )
1013cdf0e10cSrcweir     {
1014cdf0e10cSrcweir         // deCasteljau bezier arc, split at t=0.5
1015cdf0e10cSrcweir         // Foley/vanDam, p. 508
1016cdf0e10cSrcweir         const double L1x( P1x ), 		   	 L1y( P1y );
1017cdf0e10cSrcweir         const double L2x( (P1x + P2x)*0.5 ), L2y( (P1y + P2y)*0.5 );
1018cdf0e10cSrcweir         const double Hx ( (P2x + P3x)*0.5 ), Hy ( (P2y + P3y)*0.5 );
1019cdf0e10cSrcweir         const double L3x( (L2x + Hx)*0.5 ),  L3y( (L2y + Hy)*0.5 );
1020cdf0e10cSrcweir         const double R4x( P4x ), 		   	 R4y( P4y );
1021cdf0e10cSrcweir         const double R3x( (P3x + P4x)*0.5 ), R3y( (P3y + P4y)*0.5 );
1022cdf0e10cSrcweir         const double R2x( (Hx + R3x)*0.5 ),  R2y( (Hy + R3y)*0.5 );
1023cdf0e10cSrcweir         const double R1x( (L3x + R2x)*0.5 ), R1y( (L3y + R2y)*0.5 );
1024cdf0e10cSrcweir         const double L4x( R1x ), 		     L4y( R1y );
1025cdf0e10cSrcweir 
1026cdf0e10cSrcweir 		// subdivide further
1027cdf0e10cSrcweir         ++recursionDepth;
1028cdf0e10cSrcweir         ImplAdaptiveSubdivide(rPointIter, distance2, recursionDepth, d2, L1x, L1y, L2x, L2y, L3x, L3y, L4x, L4y);
1029cdf0e10cSrcweir         ImplAdaptiveSubdivide(rPointIter, distance2, recursionDepth, d2, R1x, R1y, R2x, R2y, R3x, R3y, R4x, R4y);
1030cdf0e10cSrcweir     }
1031cdf0e10cSrcweir 	else
1032cdf0e10cSrcweir 	{
1033cdf0e10cSrcweir 		// requested resolution reached.
1034cdf0e10cSrcweir 		// Add end points to output iterator.
1035cdf0e10cSrcweir 		// order is preserved, since this is so to say depth first traversal.
1036cdf0e10cSrcweir 		*rPointIter++ = Point( FRound(P1x), FRound(P1y) );
1037cdf0e10cSrcweir 	}
1038cdf0e10cSrcweir }
1039cdf0e10cSrcweir 
1040cdf0e10cSrcweir // =======================================================================
1041cdf0e10cSrcweir 
1042cdf0e10cSrcweir void Polygon::AdaptiveSubdivide( Polygon& rResult, const double d ) const
1043cdf0e10cSrcweir {
1044cdf0e10cSrcweir 	if( !mpImplPolygon->mpFlagAry )
1045cdf0e10cSrcweir 	{
1046cdf0e10cSrcweir 		rResult = *this;
1047cdf0e10cSrcweir 	}
1048cdf0e10cSrcweir 	else
1049cdf0e10cSrcweir 	{
1050cdf0e10cSrcweir 		sal_uInt16 i;
1051cdf0e10cSrcweir 		sal_uInt16 nPts( GetSize() );
1052cdf0e10cSrcweir 		::std::vector< Point > aPoints;
1053cdf0e10cSrcweir         aPoints.reserve( nPts );
1054cdf0e10cSrcweir 		::std::back_insert_iterator< ::std::vector< Point > > aPointIter( aPoints );
1055cdf0e10cSrcweir 
1056cdf0e10cSrcweir 		for(i=0; i<nPts;)
1057cdf0e10cSrcweir 		{
1058cdf0e10cSrcweir 			if( ( i + 3 ) < nPts )
1059cdf0e10cSrcweir             {
1060cdf0e10cSrcweir                 sal_uInt8 P1( mpImplPolygon->mpFlagAry[ i ] );
1061cdf0e10cSrcweir                 sal_uInt8 P4( mpImplPolygon->mpFlagAry[ i + 3 ] );
1062cdf0e10cSrcweir 
1063cdf0e10cSrcweir                 if( ( POLY_NORMAL == P1 || POLY_SMOOTH == P1 || POLY_SYMMTR == P1 ) &&
1064cdf0e10cSrcweir                     ( POLY_CONTROL == mpImplPolygon->mpFlagAry[ i + 1 ] ) &&
1065cdf0e10cSrcweir                     ( POLY_CONTROL == mpImplPolygon->mpFlagAry[ i + 2 ] ) &&
1066cdf0e10cSrcweir                     ( POLY_NORMAL == P4 || POLY_SMOOTH == P4 || POLY_SYMMTR == P4 ) )
1067cdf0e10cSrcweir                 {
1068cdf0e10cSrcweir                     ImplAdaptiveSubdivide( aPointIter, d*d+1.0, 0, d*d,
1069cdf0e10cSrcweir                                            mpImplPolygon->mpPointAry[ i ].X(),   mpImplPolygon->mpPointAry[ i ].Y(),
1070cdf0e10cSrcweir                                            mpImplPolygon->mpPointAry[ i+1 ].X(), mpImplPolygon->mpPointAry[ i+1 ].Y(),
1071cdf0e10cSrcweir                                            mpImplPolygon->mpPointAry[ i+2 ].X(), mpImplPolygon->mpPointAry[ i+2 ].Y(),
1072cdf0e10cSrcweir                                            mpImplPolygon->mpPointAry[ i+3 ].X(), mpImplPolygon->mpPointAry[ i+3 ].Y() );
1073cdf0e10cSrcweir                     i += 3;
1074cdf0e10cSrcweir                     continue;
1075cdf0e10cSrcweir                 }
1076cdf0e10cSrcweir             }
1077cdf0e10cSrcweir 
1078cdf0e10cSrcweir             *aPointIter++ = mpImplPolygon->mpPointAry[ i++ ];
1079cdf0e10cSrcweir 		}
1080cdf0e10cSrcweir 
1081cdf0e10cSrcweir 		// fill result polygon
1082cdf0e10cSrcweir 		rResult = Polygon( (sal_uInt16)aPoints.size() ); // ensure sufficient size for copy
1083cdf0e10cSrcweir 		::std::copy(aPoints.begin(), aPoints.end(), rResult.mpImplPolygon->mpPointAry);
1084cdf0e10cSrcweir 	}
1085cdf0e10cSrcweir }
1086cdf0e10cSrcweir 
1087cdf0e10cSrcweir // -----------------------------------------------------------------------
1088cdf0e10cSrcweir 
1089cdf0e10cSrcweir void Polygon::GetIntersection( const PolyPolygon& rPolyPoly, PolyPolygon& rResult ) const
1090cdf0e10cSrcweir {
1091cdf0e10cSrcweir 	const PolyPolygon aTmp( *this );
1092cdf0e10cSrcweir 	aTmp.GetIntersection( rPolyPoly, rResult );
1093cdf0e10cSrcweir }
1094cdf0e10cSrcweir 
1095cdf0e10cSrcweir // -----------------------------------------------------------------------
1096cdf0e10cSrcweir 
1097cdf0e10cSrcweir void Polygon::GetUnion( const PolyPolygon& rPolyPoly, PolyPolygon& rResult ) const
1098cdf0e10cSrcweir {
1099cdf0e10cSrcweir 	const PolyPolygon aTmp( *this );
1100cdf0e10cSrcweir 	aTmp.GetUnion( rPolyPoly, rResult );
1101cdf0e10cSrcweir }
1102cdf0e10cSrcweir 
1103cdf0e10cSrcweir // -----------------------------------------------------------------------
1104cdf0e10cSrcweir 
1105cdf0e10cSrcweir void Polygon::GetDifference( const PolyPolygon& rPolyPoly, PolyPolygon& rResult ) const
1106cdf0e10cSrcweir {
1107cdf0e10cSrcweir 	const PolyPolygon aTmp( *this );
1108cdf0e10cSrcweir 	aTmp.GetDifference( rPolyPoly, rResult );
1109cdf0e10cSrcweir }
1110cdf0e10cSrcweir 
1111cdf0e10cSrcweir // -----------------------------------------------------------------------
1112cdf0e10cSrcweir 
1113cdf0e10cSrcweir void Polygon::GetXOR( const PolyPolygon& rPolyPoly, PolyPolygon& rResult ) const
1114cdf0e10cSrcweir {
1115cdf0e10cSrcweir 	const PolyPolygon aTmp( *this );
1116cdf0e10cSrcweir 	aTmp.GetXOR( rPolyPoly, rResult );
1117cdf0e10cSrcweir }
1118cdf0e10cSrcweir 
1119cdf0e10cSrcweir // -----------------------------------------------------------------------
1120cdf0e10cSrcweir 
1121cdf0e10cSrcweir void Polygon::ImplReduceEdges( Polygon& rPoly, const double& rArea, sal_uInt16 nPercent )
1122cdf0e10cSrcweir {
1123cdf0e10cSrcweir 	const double	fBound = 2000.0 * ( 100 - nPercent ) * 0.01;
1124cdf0e10cSrcweir 	sal_uInt16			nNumNoChange = 0, nNumRuns = 0;
1125cdf0e10cSrcweir 
1126cdf0e10cSrcweir 	while( nNumNoChange < 2 )
1127cdf0e10cSrcweir 	{
1128cdf0e10cSrcweir 		sal_uInt16	nPntCnt = rPoly.GetSize(), nNewPos = 0;
1129cdf0e10cSrcweir 		Polygon	aNewPoly( nPntCnt );
1130cdf0e10cSrcweir 		sal_Bool	bChangeInThisRun = sal_False;
1131cdf0e10cSrcweir 
1132cdf0e10cSrcweir 		for( sal_uInt16 n = 0; n < nPntCnt; n++ )
1133cdf0e10cSrcweir 		{
1134cdf0e10cSrcweir 			sal_Bool bDeletePoint = sal_False;
1135cdf0e10cSrcweir 
1136cdf0e10cSrcweir 			if( ( n + nNumRuns ) % 2 )
1137cdf0e10cSrcweir 			{
1138cdf0e10cSrcweir 				sal_uInt16		nIndPrev = !n ? nPntCnt - 1 : n - 1;
1139cdf0e10cSrcweir 				sal_uInt16		nIndPrevPrev = !nIndPrev ? nPntCnt - 1 : nIndPrev - 1;
1140cdf0e10cSrcweir 				sal_uInt16		nIndNext = ( n == nPntCnt-1 ) ? 0 : n + 1;
1141cdf0e10cSrcweir 				sal_uInt16		nIndNextNext = ( nIndNext == nPntCnt - 1 ) ? 0 : nIndNext + 1;
1142cdf0e10cSrcweir 				Vector2D	aVec1( rPoly[ nIndPrev ] ); aVec1 -= rPoly[ nIndPrevPrev ];
1143cdf0e10cSrcweir 				Vector2D	aVec2( rPoly[ n ] ); aVec2 -= rPoly[ nIndPrev ];
1144cdf0e10cSrcweir 				Vector2D	aVec3( rPoly[ nIndNext ] ); aVec3 -= rPoly[ n ];
1145cdf0e10cSrcweir 				Vector2D	aVec4( rPoly[ nIndNextNext ] ); aVec4 -= rPoly[ nIndNext ];
1146cdf0e10cSrcweir 				double		fDist1 = aVec1.GetLength(), fDist2 = aVec2.GetLength();
1147cdf0e10cSrcweir 				double		fDist3 = aVec3.GetLength(), fDist4 = aVec4.GetLength();
1148cdf0e10cSrcweir 				double		fTurnB = aVec2.Normalize().Scalar( aVec3.Normalize() );
1149cdf0e10cSrcweir 
1150cdf0e10cSrcweir 				if( fabs( fTurnB ) < ( 1.0 + SMALL_DVALUE ) && fabs( fTurnB ) > ( 1.0 - SMALL_DVALUE ) )
1151cdf0e10cSrcweir 					bDeletePoint = sal_True;
1152cdf0e10cSrcweir 				else
1153cdf0e10cSrcweir 				{
1154cdf0e10cSrcweir 					Vector2D	aVecB( rPoly[ nIndNext ] );
1155cdf0e10cSrcweir 					double		fDistB = ( aVecB -= rPoly[ nIndPrev ] ).GetLength();
1156cdf0e10cSrcweir 					double		fLenWithB = fDist2 + fDist3;
1157cdf0e10cSrcweir 					double		fLenFact = ( fDistB != 0.0 ) ? fLenWithB / fDistB : 1.0;
1158cdf0e10cSrcweir 					double		fTurnPrev = aVec1.Normalize().Scalar( aVec2 );
1159cdf0e10cSrcweir 					double		fTurnNext = aVec3.Scalar( aVec4.Normalize() );
1160cdf0e10cSrcweir 					double		fGradPrev, fGradB, fGradNext;
1161cdf0e10cSrcweir 
1162cdf0e10cSrcweir 					if( fabs( fTurnPrev ) < ( 1.0 + SMALL_DVALUE ) && fabs( fTurnPrev ) > ( 1.0 - SMALL_DVALUE ) )
1163cdf0e10cSrcweir 						fGradPrev = 0.0;
1164cdf0e10cSrcweir 					else
1165cdf0e10cSrcweir 						fGradPrev = acos( fTurnPrev ) / ( aVec1.IsNegative( aVec2 ) ? -F_PI180 : F_PI180 );
1166cdf0e10cSrcweir 
1167cdf0e10cSrcweir 					fGradB = acos( fTurnB ) / ( aVec2.IsNegative( aVec3 ) ? -F_PI180 : F_PI180 );
1168cdf0e10cSrcweir 
1169cdf0e10cSrcweir 					if( fabs( fTurnNext ) < ( 1.0 + SMALL_DVALUE ) && fabs( fTurnNext ) > ( 1.0 - SMALL_DVALUE ) )
1170cdf0e10cSrcweir 						fGradNext = 0.0;
1171cdf0e10cSrcweir 					else
1172cdf0e10cSrcweir 						fGradNext = acos( fTurnNext ) / ( aVec3.IsNegative( aVec4 ) ? -F_PI180 : F_PI180 );
1173cdf0e10cSrcweir 
1174cdf0e10cSrcweir 					if( ( fGradPrev > 0.0 && fGradB < 0.0 && fGradNext > 0.0 ) ||
1175cdf0e10cSrcweir 						( fGradPrev < 0.0 && fGradB > 0.0 && fGradNext < 0.0 ) )
1176cdf0e10cSrcweir 					{
1177cdf0e10cSrcweir 						if( ( fLenFact < ( FSQRT2 + SMALL_DVALUE ) ) &&
1178cdf0e10cSrcweir 							( ( ( fDist1 + fDist4 ) / ( fDist2 + fDist3 ) ) * 2000.0 ) > fBound )
1179cdf0e10cSrcweir 						{
1180cdf0e10cSrcweir 							bDeletePoint = sal_True;
1181cdf0e10cSrcweir 						}
1182cdf0e10cSrcweir 					}
1183cdf0e10cSrcweir 					else
1184cdf0e10cSrcweir 					{
1185cdf0e10cSrcweir 						double fRelLen = 1.0 - sqrt( fDistB / rArea );
1186cdf0e10cSrcweir 
1187cdf0e10cSrcweir 						if( fRelLen < 0.0 )
1188cdf0e10cSrcweir 							fRelLen = 0.0;
1189cdf0e10cSrcweir 						else if( fRelLen > 1.0 )
1190cdf0e10cSrcweir 							fRelLen = 1.0;
1191cdf0e10cSrcweir 
1192cdf0e10cSrcweir 						if( ( (sal_uInt32) ( ( ( fLenFact - 1.0 ) * 1000000.0 ) + 0.5 ) < fBound ) &&
1193cdf0e10cSrcweir 							( fabs( fGradB ) <= ( fRelLen * fBound * 0.01 ) ) )
1194cdf0e10cSrcweir 						{
1195cdf0e10cSrcweir 							bDeletePoint = sal_True;
1196cdf0e10cSrcweir 						}
1197cdf0e10cSrcweir 					}
1198cdf0e10cSrcweir 				}
1199cdf0e10cSrcweir 			}
1200cdf0e10cSrcweir 
1201cdf0e10cSrcweir 			if( !bDeletePoint )
1202cdf0e10cSrcweir 				aNewPoly[ nNewPos++ ] = rPoly[ n ];
1203cdf0e10cSrcweir 			else
1204cdf0e10cSrcweir 				bChangeInThisRun = sal_True;
1205cdf0e10cSrcweir 		}
1206cdf0e10cSrcweir 
1207cdf0e10cSrcweir 		if( bChangeInThisRun && nNewPos )
1208cdf0e10cSrcweir 		{
1209cdf0e10cSrcweir 			aNewPoly.SetSize( nNewPos );
1210cdf0e10cSrcweir 			rPoly = aNewPoly;
1211cdf0e10cSrcweir 			nNumNoChange = 0;
1212cdf0e10cSrcweir 		}
1213cdf0e10cSrcweir 		else
1214cdf0e10cSrcweir 			nNumNoChange++;
1215cdf0e10cSrcweir 
1216cdf0e10cSrcweir 		nNumRuns++;
1217cdf0e10cSrcweir 	}
1218cdf0e10cSrcweir }
1219cdf0e10cSrcweir 
1220cdf0e10cSrcweir // -----------------------------------------------------------------------
1221cdf0e10cSrcweir 
1222cdf0e10cSrcweir void Polygon::Move( long nHorzMove, long nVertMove )
1223cdf0e10cSrcweir {
1224cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
1225cdf0e10cSrcweir 
1226cdf0e10cSrcweir 	// Diese Abfrage sollte man fuer die DrawEngine durchfuehren
1227cdf0e10cSrcweir 	if ( !nHorzMove && !nVertMove )
1228cdf0e10cSrcweir 		return;
1229cdf0e10cSrcweir 
1230cdf0e10cSrcweir 	ImplMakeUnique();
1231cdf0e10cSrcweir 
1232cdf0e10cSrcweir 	// Punkte verschieben
1233cdf0e10cSrcweir 	sal_uInt16 nCount = mpImplPolygon->mnPoints;
1234cdf0e10cSrcweir 	for ( sal_uInt16 i = 0; i < nCount; i++ )
1235cdf0e10cSrcweir 	{
1236cdf0e10cSrcweir 		Point* pPt = &(mpImplPolygon->mpPointAry[i]);
1237cdf0e10cSrcweir 		pPt->X() += nHorzMove;
1238cdf0e10cSrcweir 		pPt->Y() += nVertMove;
1239cdf0e10cSrcweir 	}
1240cdf0e10cSrcweir }
1241cdf0e10cSrcweir 
1242cdf0e10cSrcweir // -----------------------------------------------------------------------
1243cdf0e10cSrcweir 
1244cdf0e10cSrcweir void Polygon::Translate(const Point& rTrans)
1245cdf0e10cSrcweir {
1246cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
1247cdf0e10cSrcweir 	ImplMakeUnique();
1248cdf0e10cSrcweir 
1249cdf0e10cSrcweir 	for ( sal_uInt16 i = 0, nCount = mpImplPolygon->mnPoints; i < nCount; i++ )
1250cdf0e10cSrcweir 		mpImplPolygon->mpPointAry[ i ] += rTrans;
1251cdf0e10cSrcweir }
1252cdf0e10cSrcweir 
1253cdf0e10cSrcweir // -----------------------------------------------------------------------
1254cdf0e10cSrcweir 
1255cdf0e10cSrcweir void Polygon::Scale( double fScaleX, double fScaleY )
1256cdf0e10cSrcweir {
1257cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
1258cdf0e10cSrcweir 	ImplMakeUnique();
1259cdf0e10cSrcweir 
1260cdf0e10cSrcweir 	for ( sal_uInt16 i = 0, nCount = mpImplPolygon->mnPoints; i < nCount; i++ )
1261cdf0e10cSrcweir 	{
1262cdf0e10cSrcweir 		Point& rPnt = mpImplPolygon->mpPointAry[i];
1263cdf0e10cSrcweir 		rPnt.X() = (long) ( fScaleX * rPnt.X() );
1264cdf0e10cSrcweir 		rPnt.Y() = (long) ( fScaleY * rPnt.Y() );
1265cdf0e10cSrcweir 	}
1266cdf0e10cSrcweir }
1267cdf0e10cSrcweir 
1268cdf0e10cSrcweir // -----------------------------------------------------------------------
1269cdf0e10cSrcweir 
1270cdf0e10cSrcweir void Polygon::Rotate( const Point& rCenter, sal_uInt16 nAngle10 )
1271cdf0e10cSrcweir {
1272cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
1273cdf0e10cSrcweir 	nAngle10 %= 3600;
1274cdf0e10cSrcweir 
1275cdf0e10cSrcweir 	if( nAngle10 )
1276cdf0e10cSrcweir 	{
1277cdf0e10cSrcweir 		const double fAngle = F_PI1800 * nAngle10;
1278cdf0e10cSrcweir 		Rotate( rCenter, sin( fAngle ), cos( fAngle ) );
1279cdf0e10cSrcweir 	}
1280cdf0e10cSrcweir }
1281cdf0e10cSrcweir 
1282cdf0e10cSrcweir // -----------------------------------------------------------------------
1283cdf0e10cSrcweir 
1284cdf0e10cSrcweir void Polygon::Rotate( const Point& rCenter, double fSin, double fCos )
1285cdf0e10cSrcweir {
1286cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
1287cdf0e10cSrcweir 	ImplMakeUnique();
1288cdf0e10cSrcweir 
1289cdf0e10cSrcweir 	long nX, nY;
1290cdf0e10cSrcweir 	long nCenterX = rCenter.X();
1291cdf0e10cSrcweir 	long nCenterY = rCenter.Y();
1292cdf0e10cSrcweir 
1293cdf0e10cSrcweir 	for( sal_uInt16 i = 0, nCount = mpImplPolygon->mnPoints; i < nCount; i++ )
1294cdf0e10cSrcweir 	{
1295cdf0e10cSrcweir 		Point& rPt = mpImplPolygon->mpPointAry[ i ];
1296cdf0e10cSrcweir 
1297cdf0e10cSrcweir 		nX = rPt.X() - nCenterX;
1298cdf0e10cSrcweir 		nY = rPt.Y() - nCenterY;
1299cdf0e10cSrcweir 		rPt.X() = (long) FRound( fCos * nX + fSin * nY ) + nCenterX;
1300cdf0e10cSrcweir 		rPt.Y() = -(long) FRound( fSin * nX - fCos * nY ) + nCenterY;
1301cdf0e10cSrcweir 	}
1302cdf0e10cSrcweir }
1303cdf0e10cSrcweir 
1304cdf0e10cSrcweir // -----------------------------------------------------------------------
1305cdf0e10cSrcweir 
1306cdf0e10cSrcweir void Polygon::SlantX( long nYRef, double fSin, double fCos )
1307cdf0e10cSrcweir {
1308cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
1309cdf0e10cSrcweir 	ImplMakeUnique();
1310cdf0e10cSrcweir 
1311cdf0e10cSrcweir 	for( sal_uInt16 i = 0, nCount = mpImplPolygon->mnPoints; i < nCount; i++ )
1312cdf0e10cSrcweir 	{
1313cdf0e10cSrcweir 		Point&		rPnt = mpImplPolygon->mpPointAry[ i ];
1314cdf0e10cSrcweir 		const long	nDy = rPnt.Y() - nYRef;
1315cdf0e10cSrcweir 
1316cdf0e10cSrcweir 		rPnt.X() += (long)( fSin * nDy );
1317cdf0e10cSrcweir 		rPnt.Y() = nYRef + (long)( fCos * nDy );
1318cdf0e10cSrcweir 	}
1319cdf0e10cSrcweir }
1320cdf0e10cSrcweir 
1321cdf0e10cSrcweir // -----------------------------------------------------------------------
1322cdf0e10cSrcweir 
1323cdf0e10cSrcweir void Polygon::SlantY( long nXRef, double fSin, double fCos )
1324cdf0e10cSrcweir {
1325cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
1326cdf0e10cSrcweir 	ImplMakeUnique();
1327cdf0e10cSrcweir 
1328cdf0e10cSrcweir 	for( sal_uInt16 i = 0, nCount = mpImplPolygon->mnPoints; i < nCount; i++ )
1329cdf0e10cSrcweir 	{
1330cdf0e10cSrcweir 		Point&		rPnt = mpImplPolygon->mpPointAry[ i ];
1331cdf0e10cSrcweir 		const long	nDx = rPnt.X() - nXRef;
1332cdf0e10cSrcweir 
1333cdf0e10cSrcweir 		rPnt.X() = nXRef + (long)( fCos * nDx );
1334cdf0e10cSrcweir 		rPnt.Y() -= (long)( fSin * nDx );
1335cdf0e10cSrcweir 	}
1336cdf0e10cSrcweir }
1337cdf0e10cSrcweir 
1338cdf0e10cSrcweir // -----------------------------------------------------------------------
1339cdf0e10cSrcweir 
1340cdf0e10cSrcweir void Polygon::Distort( const Rectangle& rRefRect, const Polygon& rDistortedRect )
1341cdf0e10cSrcweir {
1342cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
1343cdf0e10cSrcweir 	ImplMakeUnique();
1344cdf0e10cSrcweir 
1345cdf0e10cSrcweir 	long	Xr, Wr, X1, X2, X3, X4;
1346cdf0e10cSrcweir 	long	Yr, Hr, Y1, Y2, Y3, Y4;
1347cdf0e10cSrcweir 	double	fTx, fTy, fUx, fUy;
1348cdf0e10cSrcweir 
1349cdf0e10cSrcweir 	Xr = rRefRect.Left();
1350cdf0e10cSrcweir 	Yr = rRefRect.Top();
1351cdf0e10cSrcweir 	Wr = rRefRect.GetWidth();
1352cdf0e10cSrcweir 	Hr = rRefRect.GetHeight();
1353cdf0e10cSrcweir 
1354cdf0e10cSrcweir 	if( Wr && Hr )
1355cdf0e10cSrcweir 	{
1356cdf0e10cSrcweir 		DBG_ASSERT( rDistortedRect.mpImplPolygon->mnPoints >= 4, "Distort rect too small!" );
1357cdf0e10cSrcweir 
1358cdf0e10cSrcweir 		X1 = rDistortedRect[0].X();
1359cdf0e10cSrcweir 		Y1 = rDistortedRect[0].Y();
1360cdf0e10cSrcweir 		X2 = rDistortedRect[1].X();
1361cdf0e10cSrcweir 		Y2 = rDistortedRect[1].Y();
1362cdf0e10cSrcweir 		X3 = rDistortedRect[3].X();
1363cdf0e10cSrcweir 		Y3 = rDistortedRect[3].Y();
1364cdf0e10cSrcweir 		X4 = rDistortedRect[2].X();
1365cdf0e10cSrcweir 		Y4 = rDistortedRect[2].Y();
1366cdf0e10cSrcweir 
1367cdf0e10cSrcweir 		for( sal_uInt16 i = 0, nCount = mpImplPolygon->mnPoints; i < nCount; i++ )
1368cdf0e10cSrcweir 		{
1369cdf0e10cSrcweir 			Point& rPnt = mpImplPolygon->mpPointAry[ i ];
1370cdf0e10cSrcweir 
1371cdf0e10cSrcweir 			fTx = (double)( rPnt.X() - Xr) / Wr;
1372cdf0e10cSrcweir 			fTy = (double)( rPnt.Y() - Yr) / Hr;
1373cdf0e10cSrcweir 			fUx = 1.0 - fTx;
1374cdf0e10cSrcweir 			fUy = 1.0 - fTy;
1375cdf0e10cSrcweir 
1376cdf0e10cSrcweir 			rPnt.X() = (long) ( fUy * (fUx * X1 + fTx * X2) + fTy * (fUx * X3 + fTx * X4) );
1377cdf0e10cSrcweir 			rPnt.Y() = (long) ( fUx * (fUy * Y1 + fTy * Y3) + fTx * (fUy * Y2 + fTy * Y4) );
1378cdf0e10cSrcweir 		}
1379cdf0e10cSrcweir 	}
1380cdf0e10cSrcweir }
1381cdf0e10cSrcweir 
1382cdf0e10cSrcweir // -----------------------------------------------------------------------
1383cdf0e10cSrcweir 
1384cdf0e10cSrcweir class ImplPointFilter
1385cdf0e10cSrcweir {
1386cdf0e10cSrcweir public:
1387cdf0e10cSrcweir 	virtual void LastPoint() = 0;
1388cdf0e10cSrcweir 	virtual void Input( const Point& rPoint ) = 0;
1389cdf0e10cSrcweir };
1390cdf0e10cSrcweir 
1391cdf0e10cSrcweir class ImplPolygonPointFilter : public ImplPointFilter
1392cdf0e10cSrcweir {
1393cdf0e10cSrcweir public:
1394cdf0e10cSrcweir 	ImplPolygon*	mpPoly; 	// Nicht loeschen, wird dem Polygon zugewiesen
1395cdf0e10cSrcweir 	sal_uInt16			mnSize;
1396cdf0e10cSrcweir 
1397cdf0e10cSrcweir 					ImplPolygonPointFilter( sal_uInt16 nDestSize ) :
1398cdf0e10cSrcweir 						mnSize( 0 )
1399cdf0e10cSrcweir 					{
1400cdf0e10cSrcweir 						mpPoly = new ImplPolygon( nDestSize );
1401cdf0e10cSrcweir 					}
1402cdf0e10cSrcweir 
1403cdf0e10cSrcweir 	virtual void	LastPoint();
1404cdf0e10cSrcweir 	virtual void	Input( const Point& rPoint );
1405cdf0e10cSrcweir };
1406cdf0e10cSrcweir 
1407cdf0e10cSrcweir void ImplPolygonPointFilter::Input( const Point& rPoint )
1408cdf0e10cSrcweir {
1409cdf0e10cSrcweir 	if ( !mnSize || (rPoint != mpPoly->mpPointAry[mnSize-1]) )
1410cdf0e10cSrcweir 	{
1411cdf0e10cSrcweir 		mnSize++;
1412cdf0e10cSrcweir 		if ( mnSize > mpPoly->mnPoints )
1413cdf0e10cSrcweir 			mpPoly->ImplSetSize( mnSize );
1414cdf0e10cSrcweir 		mpPoly->mpPointAry[mnSize-1] = rPoint;
1415cdf0e10cSrcweir 	}
1416cdf0e10cSrcweir }
1417cdf0e10cSrcweir 
1418cdf0e10cSrcweir void ImplPolygonPointFilter::LastPoint()
1419cdf0e10cSrcweir {
1420cdf0e10cSrcweir 	if ( mnSize < mpPoly->mnPoints )
1421cdf0e10cSrcweir 		mpPoly->ImplSetSize( mnSize );
1422cdf0e10cSrcweir };
1423cdf0e10cSrcweir 
1424cdf0e10cSrcweir class ImplEdgePointFilter : public ImplPointFilter
1425cdf0e10cSrcweir {
1426cdf0e10cSrcweir 	Point				maFirstPoint;
1427cdf0e10cSrcweir 	Point				maLastPoint;
1428cdf0e10cSrcweir 	ImplPointFilter&	mrNextFilter;
1429cdf0e10cSrcweir 	const long			mnLow;
1430cdf0e10cSrcweir 	const long			mnHigh;
1431cdf0e10cSrcweir 	const int			mnEdge;
1432cdf0e10cSrcweir 	int 				mnLastOutside;
1433cdf0e10cSrcweir 	sal_Bool				mbFirst;
1434cdf0e10cSrcweir 
1435cdf0e10cSrcweir public:
1436cdf0e10cSrcweir 						ImplEdgePointFilter( int nEdge, long nLow, long nHigh,
1437cdf0e10cSrcweir 											 ImplPointFilter& rNextFilter ) :
1438cdf0e10cSrcweir 							mrNextFilter( rNextFilter ),
1439cdf0e10cSrcweir 							mnLow( nLow ),
1440cdf0e10cSrcweir 							mnHigh( nHigh ),
1441cdf0e10cSrcweir 							mnEdge( nEdge ),
1442cdf0e10cSrcweir 							mbFirst( sal_True )
1443cdf0e10cSrcweir 						{
1444cdf0e10cSrcweir 						}
1445cdf0e10cSrcweir 
1446cdf0e10cSrcweir 	Point				EdgeSection( const Point& rPoint, int nEdge ) const;
1447cdf0e10cSrcweir 	int 				VisibleSide( const Point& rPoint ) const;
1448cdf0e10cSrcweir 	int 				IsPolygon() const
1449cdf0e10cSrcweir 							{ return maFirstPoint == maLastPoint; }
1450cdf0e10cSrcweir 
1451cdf0e10cSrcweir 	virtual void		Input( const Point& rPoint );
1452cdf0e10cSrcweir 	virtual void		LastPoint();
1453cdf0e10cSrcweir };
1454cdf0e10cSrcweir 
1455cdf0e10cSrcweir inline int ImplEdgePointFilter::VisibleSide( const Point& rPoint ) const
1456cdf0e10cSrcweir {
1457cdf0e10cSrcweir 	if ( mnEdge & EDGE_HORZ )
1458cdf0e10cSrcweir 	{
1459cdf0e10cSrcweir 		return rPoint.X() < mnLow ? EDGE_LEFT :
1460cdf0e10cSrcweir 									 rPoint.X() > mnHigh ? EDGE_RIGHT : 0;
1461cdf0e10cSrcweir 	}
1462cdf0e10cSrcweir 	else
1463cdf0e10cSrcweir 	{
1464cdf0e10cSrcweir 		return rPoint.Y() < mnLow ? EDGE_TOP :
1465cdf0e10cSrcweir 									 rPoint.Y() > mnHigh ? EDGE_BOTTOM : 0;
1466cdf0e10cSrcweir 	}
1467cdf0e10cSrcweir }
1468cdf0e10cSrcweir 
1469cdf0e10cSrcweir Point ImplEdgePointFilter::EdgeSection( const Point& rPoint, int nEdge ) const
1470cdf0e10cSrcweir {
1471cdf0e10cSrcweir 	long lx = maLastPoint.X();
1472cdf0e10cSrcweir 	long ly = maLastPoint.Y();
1473cdf0e10cSrcweir 	long md = rPoint.X() - lx;
1474cdf0e10cSrcweir 	long mn = rPoint.Y() - ly;
1475cdf0e10cSrcweir 	long nNewX;
1476cdf0e10cSrcweir 	long nNewY;
1477cdf0e10cSrcweir 
1478cdf0e10cSrcweir 	if ( nEdge & EDGE_VERT )
1479cdf0e10cSrcweir 	{
1480cdf0e10cSrcweir 		nNewY = (nEdge == EDGE_TOP) ? mnLow : mnHigh;
1481cdf0e10cSrcweir 		long dy = nNewY - ly;
1482cdf0e10cSrcweir 		if ( !md )
1483cdf0e10cSrcweir 			nNewX = lx;
1484cdf0e10cSrcweir 		else if ( (LONG_MAX / Abs(md)) >= Abs(dy) )
1485cdf0e10cSrcweir 			nNewX = (dy * md) / mn + lx;
1486cdf0e10cSrcweir 		else
1487cdf0e10cSrcweir 		{
1488cdf0e10cSrcweir 			BigInt ady = dy;
1489cdf0e10cSrcweir 			ady *= md;
1490cdf0e10cSrcweir 			if( ady.IsNeg() )
1491cdf0e10cSrcweir 				if( mn < 0 )
1492cdf0e10cSrcweir 					ady += mn/2;
1493cdf0e10cSrcweir 				else
1494cdf0e10cSrcweir 					ady -= (mn-1)/2;
1495cdf0e10cSrcweir 			else
1496cdf0e10cSrcweir 				if( mn < 0 )
1497cdf0e10cSrcweir 					ady -= (mn+1)/2;
1498cdf0e10cSrcweir 				else
1499cdf0e10cSrcweir 					ady += mn/2;
1500cdf0e10cSrcweir 			ady /= mn;
1501cdf0e10cSrcweir 			nNewX = (long)ady + lx;
1502cdf0e10cSrcweir 		}
1503cdf0e10cSrcweir 	}
1504cdf0e10cSrcweir 	else
1505cdf0e10cSrcweir 	{
1506cdf0e10cSrcweir 		nNewX = (nEdge == EDGE_LEFT) ? mnLow : mnHigh;
1507cdf0e10cSrcweir 		long dx = nNewX - lx;
1508cdf0e10cSrcweir 		if ( !mn )
1509cdf0e10cSrcweir 			nNewY = ly;
1510cdf0e10cSrcweir 		else if ( (LONG_MAX / Abs(mn)) >= Abs(dx) )
1511cdf0e10cSrcweir 			nNewY = (dx * mn) / md + ly;
1512cdf0e10cSrcweir 		else
1513cdf0e10cSrcweir 		{
1514cdf0e10cSrcweir 			BigInt adx = dx;
1515cdf0e10cSrcweir 			adx *= mn;
1516cdf0e10cSrcweir 			if( adx.IsNeg() )
1517cdf0e10cSrcweir 				if( md < 0 )
1518cdf0e10cSrcweir 					adx += md/2;
1519cdf0e10cSrcweir 				else
1520cdf0e10cSrcweir 					adx -= (md-1)/2;
1521cdf0e10cSrcweir 			else
1522cdf0e10cSrcweir 				if( md < 0 )
1523cdf0e10cSrcweir 					adx -= (md+1)/2;
1524cdf0e10cSrcweir 				else
1525cdf0e10cSrcweir 					adx += md/2;
1526cdf0e10cSrcweir 			adx /= md;
1527cdf0e10cSrcweir 			nNewY = (long)adx + ly;
1528cdf0e10cSrcweir 		}
1529cdf0e10cSrcweir 	}
1530cdf0e10cSrcweir 
1531cdf0e10cSrcweir 	return Point( nNewX, nNewY );
1532cdf0e10cSrcweir }
1533cdf0e10cSrcweir 
1534cdf0e10cSrcweir void ImplEdgePointFilter::Input( const Point& rPoint )
1535cdf0e10cSrcweir {
1536cdf0e10cSrcweir 	int nOutside = VisibleSide( rPoint );
1537cdf0e10cSrcweir 
1538cdf0e10cSrcweir 	if ( mbFirst )
1539cdf0e10cSrcweir 	{
1540cdf0e10cSrcweir 		maFirstPoint = rPoint;
1541cdf0e10cSrcweir 		mbFirst 	 = sal_False;
1542cdf0e10cSrcweir 		if ( !nOutside )
1543cdf0e10cSrcweir 			mrNextFilter.Input( rPoint );
1544cdf0e10cSrcweir 	}
1545cdf0e10cSrcweir 	else if ( rPoint == maLastPoint )
1546cdf0e10cSrcweir 		return;
1547cdf0e10cSrcweir 	else if ( !nOutside )
1548cdf0e10cSrcweir 	{
1549cdf0e10cSrcweir 		if ( mnLastOutside )
1550cdf0e10cSrcweir 			mrNextFilter.Input( EdgeSection( rPoint, mnLastOutside ) );
1551cdf0e10cSrcweir 		mrNextFilter.Input( rPoint );
1552cdf0e10cSrcweir 	}
1553cdf0e10cSrcweir 	else if ( !mnLastOutside )
1554cdf0e10cSrcweir 		mrNextFilter.Input( EdgeSection( rPoint, nOutside ) );
1555cdf0e10cSrcweir 	else if ( nOutside != mnLastOutside )
1556cdf0e10cSrcweir 	{
1557cdf0e10cSrcweir 		mrNextFilter.Input( EdgeSection( rPoint, mnLastOutside ) );
1558cdf0e10cSrcweir 		mrNextFilter.Input( EdgeSection( rPoint, nOutside ) );
1559cdf0e10cSrcweir 	}
1560cdf0e10cSrcweir 
1561cdf0e10cSrcweir 	maLastPoint    = rPoint;
1562cdf0e10cSrcweir 	mnLastOutside  = nOutside;
1563cdf0e10cSrcweir }
1564cdf0e10cSrcweir 
1565cdf0e10cSrcweir void ImplEdgePointFilter::LastPoint()
1566cdf0e10cSrcweir {
1567cdf0e10cSrcweir 	if ( !mbFirst )
1568cdf0e10cSrcweir 	{
1569cdf0e10cSrcweir 		int nOutside = VisibleSide( maFirstPoint );
1570cdf0e10cSrcweir 
1571cdf0e10cSrcweir 		if ( nOutside != mnLastOutside )
1572cdf0e10cSrcweir 			Input( maFirstPoint );
1573cdf0e10cSrcweir 		mrNextFilter.LastPoint();
1574cdf0e10cSrcweir 	}
1575cdf0e10cSrcweir }
1576cdf0e10cSrcweir 
1577cdf0e10cSrcweir // -----------------------------------------------------------------------
1578cdf0e10cSrcweir 
1579cdf0e10cSrcweir void Polygon::Clip( const Rectangle& rRect, sal_Bool bPolygon )
1580cdf0e10cSrcweir {
1581cdf0e10cSrcweir     // #105251# Justify rect befor edge filtering
1582cdf0e10cSrcweir     Rectangle				aJustifiedRect( rRect );
1583cdf0e10cSrcweir     aJustifiedRect.Justify();
1584cdf0e10cSrcweir 
1585cdf0e10cSrcweir 	sal_uInt16					nSourceSize = mpImplPolygon->mnPoints;
1586cdf0e10cSrcweir 	ImplPolygonPointFilter	aPolygon( nSourceSize );
1587cdf0e10cSrcweir 	ImplEdgePointFilter 	aHorzFilter( EDGE_HORZ, aJustifiedRect.Left(), aJustifiedRect.Right(),
1588cdf0e10cSrcweir 										 aPolygon );
1589cdf0e10cSrcweir 	ImplEdgePointFilter 	aVertFilter( EDGE_VERT, aJustifiedRect.Top(), aJustifiedRect.Bottom(),
1590cdf0e10cSrcweir 										 aHorzFilter );
1591cdf0e10cSrcweir 
1592cdf0e10cSrcweir 	for ( sal_uInt16 i = 0; i < nSourceSize; i++ )
1593cdf0e10cSrcweir 		aVertFilter.Input( mpImplPolygon->mpPointAry[i] );
1594cdf0e10cSrcweir 	if ( bPolygon || aVertFilter.IsPolygon() )
1595cdf0e10cSrcweir 		aVertFilter.LastPoint();
1596cdf0e10cSrcweir 	else
1597cdf0e10cSrcweir 		aPolygon.LastPoint();
1598cdf0e10cSrcweir 
1599cdf0e10cSrcweir 	// Alte ImpPolygon-Daten loeschen und die vom ImpPolygonPointFilter
1600cdf0e10cSrcweir 	// zuweisen
1601cdf0e10cSrcweir 	if ( mpImplPolygon->mnRefCount )
1602cdf0e10cSrcweir 	{
1603cdf0e10cSrcweir 		if ( mpImplPolygon->mnRefCount > 1 )
1604cdf0e10cSrcweir 			mpImplPolygon->mnRefCount--;
1605cdf0e10cSrcweir 		else
1606cdf0e10cSrcweir 			delete mpImplPolygon;
1607cdf0e10cSrcweir 	}
1608cdf0e10cSrcweir 	mpImplPolygon = aPolygon.mpPoly;
1609cdf0e10cSrcweir }
1610cdf0e10cSrcweir 
1611cdf0e10cSrcweir // -----------------------------------------------------------------------
1612cdf0e10cSrcweir 
1613cdf0e10cSrcweir Rectangle Polygon::GetBoundRect() const
1614cdf0e10cSrcweir {
1615cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
1616cdf0e10cSrcweir     // Removing the assert. Bezier curves have the attribute that each single
1617cdf0e10cSrcweir     // curve segment defined by four points can not exit the four-point polygon
1618cdf0e10cSrcweir     // defined by that points. This allows to say that the curve segment can also
1619cdf0e10cSrcweir     // never leave the Range of it's defining points.
1620cdf0e10cSrcweir     // The result is that Polygon::GetBoundRect() may not create the minimal
1621cdf0e10cSrcweir     // BoundRect of the Polygon (to get that, use basegfx::B2DPolygon classes),
1622cdf0e10cSrcweir     // but will always create a valid BoundRect, at least as long as this method
1623cdf0e10cSrcweir     // 'blindly' travels over all points, including control points.
1624cdf0e10cSrcweir     //
1625cdf0e10cSrcweir 	// DBG_ASSERT( !mpImplPolygon->mpFlagAry, "GetBoundRect could fail with beziers!" );
1626cdf0e10cSrcweir 
1627cdf0e10cSrcweir 	sal_uInt16	nCount = mpImplPolygon->mnPoints;
1628cdf0e10cSrcweir 	if( ! nCount )
1629cdf0e10cSrcweir 		return Rectangle();
1630cdf0e10cSrcweir 
1631cdf0e10cSrcweir 	long	nXMin, nXMax, nYMin, nYMax;
1632cdf0e10cSrcweir 
1633cdf0e10cSrcweir 	const Point* pPt = &(mpImplPolygon->mpPointAry[0]);
1634cdf0e10cSrcweir 	nXMin = nXMax = pPt->X();
1635cdf0e10cSrcweir 	nYMin = nYMax = pPt->Y();
1636cdf0e10cSrcweir 
1637cdf0e10cSrcweir 	for ( sal_uInt16 i = 0; i < nCount; i++ )
1638cdf0e10cSrcweir 	{
1639cdf0e10cSrcweir 		pPt = &(mpImplPolygon->mpPointAry[i]);
1640cdf0e10cSrcweir 
1641cdf0e10cSrcweir 		if ( pPt->X() < nXMin )
1642cdf0e10cSrcweir 			nXMin = pPt->X();
1643cdf0e10cSrcweir 		if ( pPt->X() > nXMax )
1644cdf0e10cSrcweir 			nXMax = pPt->X();
1645cdf0e10cSrcweir 		if ( pPt->Y() < nYMin )
1646cdf0e10cSrcweir 			nYMin = pPt->Y();
1647cdf0e10cSrcweir 		if ( pPt->Y() > nYMax )
1648cdf0e10cSrcweir 			nYMax = pPt->Y();
1649cdf0e10cSrcweir 	}
1650cdf0e10cSrcweir 
1651cdf0e10cSrcweir 	return Rectangle( nXMin, nYMin, nXMax, nYMax );
1652cdf0e10cSrcweir }
1653cdf0e10cSrcweir 
1654cdf0e10cSrcweir // -----------------------------------------------------------------------
1655cdf0e10cSrcweir 
1656cdf0e10cSrcweir double Polygon::GetArea() const
1657cdf0e10cSrcweir {
1658cdf0e10cSrcweir 	const double fArea = GetSignedArea();
1659cdf0e10cSrcweir 	return( ( fArea < 0.0 ) ? -fArea : fArea );
1660cdf0e10cSrcweir }
1661cdf0e10cSrcweir 
1662cdf0e10cSrcweir // -----------------------------------------------------------------------
1663cdf0e10cSrcweir 
1664cdf0e10cSrcweir double Polygon::GetSignedArea() const
1665cdf0e10cSrcweir {
1666cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
1667cdf0e10cSrcweir 	DBG_ASSERT( !mpImplPolygon->mpFlagAry, "GetArea could fail with beziers!" );
1668cdf0e10cSrcweir 
1669cdf0e10cSrcweir 	double fArea = 0.0;
1670cdf0e10cSrcweir 
1671cdf0e10cSrcweir 	if( mpImplPolygon->mnPoints > 2 )
1672cdf0e10cSrcweir 	{
1673cdf0e10cSrcweir 		const sal_uInt16 nCount1 = mpImplPolygon->mnPoints - 1;
1674cdf0e10cSrcweir 
1675cdf0e10cSrcweir 		for( sal_uInt16 i = 0; i < nCount1; )
1676cdf0e10cSrcweir 		{
1677cdf0e10cSrcweir 			const Point& rPt = mpImplPolygon->mpPointAry[ i ];
1678cdf0e10cSrcweir 			const Point& rPt1 = mpImplPolygon->mpPointAry[ ++i ];
1679cdf0e10cSrcweir 			fArea += ( rPt.X() - rPt1.X() ) * ( rPt.Y() + rPt1.Y() );
1680cdf0e10cSrcweir 		}
1681cdf0e10cSrcweir 
1682cdf0e10cSrcweir 		const Point& rPt = mpImplPolygon->mpPointAry[ nCount1 ];
1683cdf0e10cSrcweir 		const Point& rPt0 = mpImplPolygon->mpPointAry[ 0 ];
1684cdf0e10cSrcweir 		fArea += ( rPt.X() - rPt0.X() ) * ( rPt.Y() + rPt0.Y() );
1685cdf0e10cSrcweir 	}
1686cdf0e10cSrcweir 
1687cdf0e10cSrcweir 	return fArea;
1688cdf0e10cSrcweir }
1689cdf0e10cSrcweir 
1690cdf0e10cSrcweir // -----------------------------------------------------------------------
1691cdf0e10cSrcweir 
1692cdf0e10cSrcweir sal_Bool Polygon::IsInside( const Point& rPoint ) const
1693cdf0e10cSrcweir {
1694cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
1695cdf0e10cSrcweir 	DBG_ASSERT( !mpImplPolygon->mpFlagAry, "IsInside could fail with beziers!" );
1696cdf0e10cSrcweir 
1697cdf0e10cSrcweir 	const Rectangle aBound( GetBoundRect() );
1698cdf0e10cSrcweir 	const Line		aLine( rPoint, Point( aBound.Right() + 100L, rPoint.Y() ) );
1699cdf0e10cSrcweir 	sal_uInt16			nCount = mpImplPolygon->mnPoints;
1700cdf0e10cSrcweir 	sal_uInt16			nPCounter = 0;
1701cdf0e10cSrcweir 
1702cdf0e10cSrcweir 	if ( ( nCount > 2 ) && aBound.IsInside( rPoint ) )
1703cdf0e10cSrcweir 	{
1704cdf0e10cSrcweir 		Point	aPt1( mpImplPolygon->mpPointAry[ 0 ] );
1705cdf0e10cSrcweir 		Point	aIntersection;
1706cdf0e10cSrcweir 		Point	aLastIntersection;
1707cdf0e10cSrcweir 
1708cdf0e10cSrcweir 		while ( ( aPt1 == mpImplPolygon->mpPointAry[ nCount - 1 ] ) && ( nCount > 3 ) )
1709cdf0e10cSrcweir 			nCount--;
1710cdf0e10cSrcweir 
1711cdf0e10cSrcweir 		for ( sal_uInt16 i = 1; i <= nCount; i++ )
1712cdf0e10cSrcweir 		{
1713cdf0e10cSrcweir 			const Point& rPt2 = mpImplPolygon->mpPointAry[ ( i < nCount ) ? i : 0 ];
1714cdf0e10cSrcweir 
1715cdf0e10cSrcweir 			if ( aLine.Intersection( Line( aPt1, rPt2 ), aIntersection ) )
1716cdf0e10cSrcweir 			{
1717cdf0e10cSrcweir 				// Hiermit verhindern wir das Einfuegen von
1718cdf0e10cSrcweir 				// doppelten Intersections, die gleich hintereinander folgen
1719cdf0e10cSrcweir 				if ( nPCounter )
1720cdf0e10cSrcweir 				{
1721cdf0e10cSrcweir 					if ( aIntersection != aLastIntersection )
1722cdf0e10cSrcweir 					{
1723cdf0e10cSrcweir 						aLastIntersection = aIntersection;
1724cdf0e10cSrcweir 						nPCounter++;
1725cdf0e10cSrcweir 					}
1726cdf0e10cSrcweir 				}
1727cdf0e10cSrcweir 				else
1728cdf0e10cSrcweir 				{
1729cdf0e10cSrcweir 					aLastIntersection = aIntersection;
1730cdf0e10cSrcweir 					nPCounter++;
1731cdf0e10cSrcweir 				}
1732cdf0e10cSrcweir 			}
1733cdf0e10cSrcweir 
1734cdf0e10cSrcweir 			aPt1 = rPt2;
1735cdf0e10cSrcweir 		}
1736cdf0e10cSrcweir 	}
1737cdf0e10cSrcweir 
1738cdf0e10cSrcweir 	// innerhalb, wenn die Anzahl der Schnittpunkte ungerade ist
1739cdf0e10cSrcweir 	return ( ( nPCounter & 1 ) == 1 );
1740cdf0e10cSrcweir }
1741cdf0e10cSrcweir 
1742cdf0e10cSrcweir // -----------------------------------------------------------------------
1743cdf0e10cSrcweir 
1744cdf0e10cSrcweir sal_Bool Polygon::IsRightOrientated() const
1745cdf0e10cSrcweir {
1746cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
1747cdf0e10cSrcweir 	return GetSignedArea() >= 0.0;
1748cdf0e10cSrcweir }
1749cdf0e10cSrcweir 
1750cdf0e10cSrcweir // -----------------------------------------------------------------------
1751cdf0e10cSrcweir 
1752cdf0e10cSrcweir void Polygon::Insert( sal_uInt16 nPos, const Point& rPt, PolyFlags eFlags )
1753cdf0e10cSrcweir {
1754cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
1755cdf0e10cSrcweir 	ImplMakeUnique();
1756cdf0e10cSrcweir 
1757cdf0e10cSrcweir 	if( nPos >= mpImplPolygon->mnPoints )
1758cdf0e10cSrcweir 		nPos = mpImplPolygon->mnPoints;
1759cdf0e10cSrcweir 
1760cdf0e10cSrcweir 	mpImplPolygon->ImplSplit( nPos, 1 );
1761cdf0e10cSrcweir 	mpImplPolygon->mpPointAry[ nPos ] = rPt;
1762cdf0e10cSrcweir 
1763cdf0e10cSrcweir 	if( POLY_NORMAL != eFlags )
1764cdf0e10cSrcweir 	{
1765cdf0e10cSrcweir 		mpImplPolygon->ImplCreateFlagArray();
1766cdf0e10cSrcweir 		mpImplPolygon->mpFlagAry[ nPos ] = (sal_uInt8) eFlags;
1767cdf0e10cSrcweir 	}
1768cdf0e10cSrcweir }
1769cdf0e10cSrcweir 
1770cdf0e10cSrcweir // -----------------------------------------------------------------------
1771cdf0e10cSrcweir 
1772cdf0e10cSrcweir void Polygon::Insert( sal_uInt16 nPos, const Polygon& rPoly )
1773cdf0e10cSrcweir {
1774cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
1775cdf0e10cSrcweir 	const sal_uInt16 nInsertCount = rPoly.mpImplPolygon->mnPoints;
1776cdf0e10cSrcweir 
1777cdf0e10cSrcweir 	if( nInsertCount )
1778cdf0e10cSrcweir 	{
1779cdf0e10cSrcweir 		ImplMakeUnique();
1780cdf0e10cSrcweir 
1781cdf0e10cSrcweir 		if( nPos >= mpImplPolygon->mnPoints )
1782cdf0e10cSrcweir 			nPos = mpImplPolygon->mnPoints;
1783cdf0e10cSrcweir 
1784cdf0e10cSrcweir 		if( rPoly.mpImplPolygon->mpFlagAry )
1785cdf0e10cSrcweir 			mpImplPolygon->ImplCreateFlagArray();
1786cdf0e10cSrcweir 
1787cdf0e10cSrcweir 		mpImplPolygon->ImplSplit( nPos, nInsertCount, rPoly.mpImplPolygon );
1788cdf0e10cSrcweir 	}
1789cdf0e10cSrcweir }
1790cdf0e10cSrcweir 
1791cdf0e10cSrcweir // -----------------------------------------------------------------------
1792cdf0e10cSrcweir 
1793cdf0e10cSrcweir void Polygon::Remove( sal_uInt16 nPos, sal_uInt16 nCount )
1794cdf0e10cSrcweir {
1795cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
1796cdf0e10cSrcweir 	if( nCount && ( nPos < mpImplPolygon->mnPoints ) )
1797cdf0e10cSrcweir 	{
1798cdf0e10cSrcweir 		ImplMakeUnique();
1799cdf0e10cSrcweir 		mpImplPolygon->ImplRemove( nPos, nCount );
1800cdf0e10cSrcweir 	}
1801cdf0e10cSrcweir }
1802cdf0e10cSrcweir 
1803cdf0e10cSrcweir // -----------------------------------------------------------------------
1804cdf0e10cSrcweir 
1805cdf0e10cSrcweir Point& Polygon::operator[]( sal_uInt16 nPos )
1806cdf0e10cSrcweir {
1807cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
1808cdf0e10cSrcweir 	DBG_ASSERT( nPos < mpImplPolygon->mnPoints, "Polygon::[]: nPos >= nPoints" );
1809cdf0e10cSrcweir 
1810cdf0e10cSrcweir 	ImplMakeUnique();
1811cdf0e10cSrcweir 	return mpImplPolygon->mpPointAry[nPos];
1812cdf0e10cSrcweir }
1813cdf0e10cSrcweir 
1814cdf0e10cSrcweir // -----------------------------------------------------------------------
1815cdf0e10cSrcweir 
1816cdf0e10cSrcweir Polygon& Polygon::operator=( const Polygon& rPoly )
1817cdf0e10cSrcweir {
1818cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
1819cdf0e10cSrcweir 	DBG_CHKOBJ( &rPoly, Polygon, NULL );
1820cdf0e10cSrcweir 	DBG_ASSERT( rPoly.mpImplPolygon->mnRefCount < 0xFFFFFFFE, "Polygon: RefCount overflow" );
1821cdf0e10cSrcweir 
1822cdf0e10cSrcweir 	// Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
1823cdf0e10cSrcweir 	// RefCount == 0 fuer statische Objekte
1824cdf0e10cSrcweir 	if ( rPoly.mpImplPolygon->mnRefCount )
1825cdf0e10cSrcweir 		rPoly.mpImplPolygon->mnRefCount++;
1826cdf0e10cSrcweir 
1827cdf0e10cSrcweir 	// Wenn es keine statischen ImpDaten sind, dann loeschen, wenn es
1828cdf0e10cSrcweir 	// die letzte Referenz ist, sonst Referenzcounter decrementieren
1829cdf0e10cSrcweir 	if ( mpImplPolygon->mnRefCount )
1830cdf0e10cSrcweir 	{
1831cdf0e10cSrcweir 		if ( mpImplPolygon->mnRefCount > 1 )
1832cdf0e10cSrcweir 			mpImplPolygon->mnRefCount--;
1833cdf0e10cSrcweir 		else
1834cdf0e10cSrcweir 			delete mpImplPolygon;
1835cdf0e10cSrcweir 	}
1836cdf0e10cSrcweir 
1837cdf0e10cSrcweir 	mpImplPolygon = rPoly.mpImplPolygon;
1838cdf0e10cSrcweir 	return *this;
1839cdf0e10cSrcweir }
1840cdf0e10cSrcweir 
1841cdf0e10cSrcweir // -----------------------------------------------------------------------
1842cdf0e10cSrcweir 
1843cdf0e10cSrcweir sal_Bool Polygon::operator==( const Polygon& rPoly ) const
1844cdf0e10cSrcweir {
1845cdf0e10cSrcweir 	DBG_CHKTHIS( Polygon, NULL );
1846cdf0e10cSrcweir 	DBG_CHKOBJ( &rPoly, Polygon, NULL );
1847cdf0e10cSrcweir 
1848cdf0e10cSrcweir 	if ( (rPoly.mpImplPolygon == mpImplPolygon) )
1849cdf0e10cSrcweir 		return sal_True;
1850cdf0e10cSrcweir 	else
1851cdf0e10cSrcweir 		return sal_False;
1852cdf0e10cSrcweir }
1853cdf0e10cSrcweir 
1854cdf0e10cSrcweir // -----------------------------------------------------------------------
1855cdf0e10cSrcweir 
1856cdf0e10cSrcweir sal_Bool Polygon::IsEqual( const Polygon& rPoly ) const
1857cdf0e10cSrcweir {
1858cdf0e10cSrcweir 	sal_Bool bIsEqual = sal_True;;
1859cdf0e10cSrcweir 	sal_uInt16 i;
1860cdf0e10cSrcweir 	if ( GetSize() != rPoly.GetSize() )
1861cdf0e10cSrcweir 		bIsEqual = sal_False;
1862cdf0e10cSrcweir 	else
1863cdf0e10cSrcweir 	{
1864cdf0e10cSrcweir 		for ( i = 0; i < GetSize(); i++ )
1865cdf0e10cSrcweir 		{
1866cdf0e10cSrcweir 			if ( ( GetPoint( i ) != rPoly.GetPoint( i ) ) ||
1867cdf0e10cSrcweir 				( GetFlags( i ) != rPoly.GetFlags( i ) ) )
1868cdf0e10cSrcweir 			{
1869cdf0e10cSrcweir 				bIsEqual = sal_False;
1870cdf0e10cSrcweir 				break;
1871cdf0e10cSrcweir 			}
1872cdf0e10cSrcweir 		}
1873cdf0e10cSrcweir 	}
1874cdf0e10cSrcweir 	return bIsEqual;
1875cdf0e10cSrcweir }
1876cdf0e10cSrcweir 
1877cdf0e10cSrcweir // -----------------------------------------------------------------------
1878cdf0e10cSrcweir 
1879cdf0e10cSrcweir SvStream& operator>>( SvStream& rIStream, Polygon& rPoly )
1880cdf0e10cSrcweir {
1881cdf0e10cSrcweir 	DBG_CHKOBJ( &rPoly, Polygon, NULL );
1882cdf0e10cSrcweir 	DBG_ASSERTWARNING( rIStream.GetVersion(), "Polygon::>> - Solar-Version not set on rIStream" );
1883cdf0e10cSrcweir 
1884cdf0e10cSrcweir 	sal_uInt16			i;
1885cdf0e10cSrcweir 	sal_uInt16			nStart;
1886cdf0e10cSrcweir 	sal_uInt16			nCurPoints;
1887cdf0e10cSrcweir 	sal_uInt16			nPoints;
1888cdf0e10cSrcweir 	unsigned char	bShort;
1889cdf0e10cSrcweir 	short			nShortX;
1890cdf0e10cSrcweir 	short			nShortY;
1891cdf0e10cSrcweir 	long			nLongX;
1892cdf0e10cSrcweir 	long			nLongY;
1893cdf0e10cSrcweir 
1894cdf0e10cSrcweir 	// Anzahl der Punkte einlesen und Array erzeugen
1895cdf0e10cSrcweir 	rIStream >> nPoints;
1896cdf0e10cSrcweir 	if ( rPoly.mpImplPolygon->mnRefCount != 1 )
1897cdf0e10cSrcweir 	{
1898cdf0e10cSrcweir 		if ( rPoly.mpImplPolygon->mnRefCount )
1899cdf0e10cSrcweir 			rPoly.mpImplPolygon->mnRefCount--;
1900cdf0e10cSrcweir 		rPoly.mpImplPolygon = new ImplPolygon( nPoints );
1901cdf0e10cSrcweir 	}
1902cdf0e10cSrcweir 	else
1903cdf0e10cSrcweir 		rPoly.mpImplPolygon->ImplSetSize( nPoints, sal_False );
1904cdf0e10cSrcweir 
1905cdf0e10cSrcweir 	// Je nach CompressMode das Polygon einlesen
1906cdf0e10cSrcweir 	if ( rIStream.GetCompressMode() == COMPRESSMODE_FULL )
1907cdf0e10cSrcweir 	{
1908cdf0e10cSrcweir 		i = 0;
1909cdf0e10cSrcweir 		while ( i < nPoints )
1910cdf0e10cSrcweir 		{
1911cdf0e10cSrcweir 			rIStream >> bShort >> nCurPoints;
1912cdf0e10cSrcweir 
1913cdf0e10cSrcweir 			if ( bShort )
1914cdf0e10cSrcweir 			{
1915cdf0e10cSrcweir 				for ( nStart = i; i < nStart+nCurPoints; i++ )
1916cdf0e10cSrcweir 				{
1917cdf0e10cSrcweir 					rIStream >> nShortX >> nShortY;
1918cdf0e10cSrcweir 					rPoly.mpImplPolygon->mpPointAry[i].X() = nShortX;
1919cdf0e10cSrcweir 					rPoly.mpImplPolygon->mpPointAry[i].Y() = nShortY;
1920cdf0e10cSrcweir 				}
1921cdf0e10cSrcweir 			}
1922cdf0e10cSrcweir 			else
1923cdf0e10cSrcweir 			{
1924cdf0e10cSrcweir 				for ( nStart = i; i < nStart+nCurPoints; i++ )
1925cdf0e10cSrcweir 				{
1926cdf0e10cSrcweir 					rIStream >> nLongX >> nLongY;
1927cdf0e10cSrcweir 					rPoly.mpImplPolygon->mpPointAry[i].X() = nLongX;
1928cdf0e10cSrcweir 					rPoly.mpImplPolygon->mpPointAry[i].Y() = nLongY;
1929cdf0e10cSrcweir 				}
1930cdf0e10cSrcweir 			}
1931cdf0e10cSrcweir 		}
1932cdf0e10cSrcweir 	}
1933cdf0e10cSrcweir 	else
1934cdf0e10cSrcweir 	{
1935cdf0e10cSrcweir 		// Feststellen, ob ueber die Operatoren geschrieben werden muss
1936cdf0e10cSrcweir #if (SAL_TYPES_SIZEOFLONG) != 4
1937cdf0e10cSrcweir 		if ( 1 )
1938cdf0e10cSrcweir #else
1939cdf0e10cSrcweir #ifdef OSL_BIGENDIAN
1940cdf0e10cSrcweir 		if ( rIStream.GetNumberFormatInt() != NUMBERFORMAT_INT_BIGENDIAN )
1941cdf0e10cSrcweir #else
1942cdf0e10cSrcweir 		if ( rIStream.GetNumberFormatInt() != NUMBERFORMAT_INT_LITTLEENDIAN )
1943cdf0e10cSrcweir #endif
1944cdf0e10cSrcweir #endif
1945cdf0e10cSrcweir 		{
1946cdf0e10cSrcweir 			for( i = 0; i < nPoints; i++ )
1947cdf0e10cSrcweir 			{
1948cdf0e10cSrcweir 				rIStream >> rPoly.mpImplPolygon->mpPointAry[i].X()
1949cdf0e10cSrcweir 						 >> rPoly.mpImplPolygon->mpPointAry[i].Y();
1950cdf0e10cSrcweir 			}
1951cdf0e10cSrcweir 		}
1952cdf0e10cSrcweir 		else
1953cdf0e10cSrcweir 			rIStream.Read( rPoly.mpImplPolygon->mpPointAry, nPoints*sizeof(Point) );
1954cdf0e10cSrcweir 	}
1955cdf0e10cSrcweir 
1956cdf0e10cSrcweir 	return rIStream;
1957cdf0e10cSrcweir }
1958cdf0e10cSrcweir 
1959cdf0e10cSrcweir // -----------------------------------------------------------------------
1960cdf0e10cSrcweir 
1961cdf0e10cSrcweir SvStream& operator<<( SvStream& rOStream, const Polygon& rPoly )
1962cdf0e10cSrcweir {
1963cdf0e10cSrcweir 	DBG_CHKOBJ( &rPoly, Polygon, NULL );
1964cdf0e10cSrcweir 	DBG_ASSERTWARNING( rOStream.GetVersion(), "Polygon::<< - Solar-Version not set on rOStream" );
1965cdf0e10cSrcweir 
1966cdf0e10cSrcweir 	unsigned char	bShort;
1967cdf0e10cSrcweir 	unsigned char	bCurShort;
1968cdf0e10cSrcweir 	sal_uInt16			nStart;
1969cdf0e10cSrcweir 	sal_uInt16			i;
1970cdf0e10cSrcweir 	sal_uInt16			nPoints = rPoly.GetSize();
1971cdf0e10cSrcweir 
1972cdf0e10cSrcweir 	// Anzahl der Punkte rausschreiben
1973cdf0e10cSrcweir 	rOStream << nPoints;
1974cdf0e10cSrcweir 
1975cdf0e10cSrcweir 	// Je nach CompressMode das Polygon rausschreiben
1976cdf0e10cSrcweir 	if ( rOStream.GetCompressMode() == COMPRESSMODE_FULL )
1977cdf0e10cSrcweir 	{
1978cdf0e10cSrcweir 		i = 0;
1979cdf0e10cSrcweir 		while ( i < nPoints )
1980cdf0e10cSrcweir 		{
1981cdf0e10cSrcweir 			nStart = i;
1982cdf0e10cSrcweir 
1983cdf0e10cSrcweir 			// Feststellen, welcher Typ geschrieben werden soll
1984cdf0e10cSrcweir 			if ( ((rPoly.mpImplPolygon->mpPointAry[nStart].X() >= SHRT_MIN) &&
1985cdf0e10cSrcweir 				  (rPoly.mpImplPolygon->mpPointAry[nStart].X() <= SHRT_MAX)) &&
1986cdf0e10cSrcweir 				 ((rPoly.mpImplPolygon->mpPointAry[nStart].Y() >= SHRT_MIN) &&
1987cdf0e10cSrcweir 				  (rPoly.mpImplPolygon->mpPointAry[nStart].Y() <= SHRT_MAX)) )
1988cdf0e10cSrcweir 				bShort = sal_True;
1989cdf0e10cSrcweir 			else
1990cdf0e10cSrcweir 				bShort = sal_False;
1991cdf0e10cSrcweir 			while ( i < nPoints )
1992cdf0e10cSrcweir 			{
1993cdf0e10cSrcweir 				// Feststellen, welcher Typ geschrieben werden soll
1994cdf0e10cSrcweir 				if ( ((rPoly.mpImplPolygon->mpPointAry[nStart].X() >= SHRT_MIN) &&
1995cdf0e10cSrcweir 					  (rPoly.mpImplPolygon->mpPointAry[nStart].X() <= SHRT_MAX)) &&
1996cdf0e10cSrcweir 					 ((rPoly.mpImplPolygon->mpPointAry[nStart].Y() >= SHRT_MIN) &&
1997cdf0e10cSrcweir 					  (rPoly.mpImplPolygon->mpPointAry[nStart].Y() <= SHRT_MAX)) )
1998cdf0e10cSrcweir 					bCurShort = sal_True;
1999cdf0e10cSrcweir 				else
2000cdf0e10cSrcweir 					bCurShort = sal_False;
2001cdf0e10cSrcweir 
2002cdf0e10cSrcweir 				// Wenn sich die Werte in einen anderen Bereich begeben,
2003cdf0e10cSrcweir 				// muessen wir neu rausschreiben
2004cdf0e10cSrcweir 				if ( bCurShort != bShort )
2005cdf0e10cSrcweir 				{
2006cdf0e10cSrcweir 					bShort = bCurShort;
2007cdf0e10cSrcweir 					break;
2008cdf0e10cSrcweir 				}
2009cdf0e10cSrcweir 
2010cdf0e10cSrcweir 				i++;
2011cdf0e10cSrcweir 			}
2012cdf0e10cSrcweir 
2013cdf0e10cSrcweir 			rOStream << bShort << (sal_uInt16)(i-nStart);
2014cdf0e10cSrcweir 
2015cdf0e10cSrcweir 			if ( bShort )
2016cdf0e10cSrcweir 			{
2017cdf0e10cSrcweir 				for( ; nStart < i; nStart++ )
2018cdf0e10cSrcweir 				{
2019cdf0e10cSrcweir 					rOStream << (short)rPoly.mpImplPolygon->mpPointAry[nStart].X()
2020cdf0e10cSrcweir 							 << (short)rPoly.mpImplPolygon->mpPointAry[nStart].Y();
2021cdf0e10cSrcweir 				}
2022cdf0e10cSrcweir 			}
2023cdf0e10cSrcweir 			else
2024cdf0e10cSrcweir 			{
2025cdf0e10cSrcweir 				for( ; nStart < i; nStart++ )
2026cdf0e10cSrcweir 				{
2027cdf0e10cSrcweir 					rOStream << rPoly.mpImplPolygon->mpPointAry[nStart].X()
2028cdf0e10cSrcweir 							 << rPoly.mpImplPolygon->mpPointAry[nStart].Y();
2029cdf0e10cSrcweir 				}
2030cdf0e10cSrcweir 			}
2031cdf0e10cSrcweir 		}
2032cdf0e10cSrcweir 	}
2033cdf0e10cSrcweir 	else
2034cdf0e10cSrcweir 	{
2035cdf0e10cSrcweir 		// Feststellen, ob ueber die Operatoren geschrieben werden muss
2036cdf0e10cSrcweir #if (SAL_TYPES_SIZEOFLONG) != 4
2037cdf0e10cSrcweir 		if ( 1 )
2038cdf0e10cSrcweir #else
2039cdf0e10cSrcweir #ifdef OSL_BIGENDIAN
2040cdf0e10cSrcweir 		if ( rOStream.GetNumberFormatInt() != NUMBERFORMAT_INT_BIGENDIAN )
2041cdf0e10cSrcweir #else
2042cdf0e10cSrcweir 		if ( rOStream.GetNumberFormatInt() != NUMBERFORMAT_INT_LITTLEENDIAN )
2043cdf0e10cSrcweir #endif
2044cdf0e10cSrcweir #endif
2045cdf0e10cSrcweir 		{
2046cdf0e10cSrcweir 			for( i = 0; i < nPoints; i++ )
2047cdf0e10cSrcweir 			{
2048cdf0e10cSrcweir 				rOStream << rPoly.mpImplPolygon->mpPointAry[i].X()
2049cdf0e10cSrcweir 						 << rPoly.mpImplPolygon->mpPointAry[i].Y();
2050cdf0e10cSrcweir 			}
2051cdf0e10cSrcweir 		}
2052cdf0e10cSrcweir 		else
2053cdf0e10cSrcweir 		{
2054cdf0e10cSrcweir 			if ( nPoints )
2055cdf0e10cSrcweir 				rOStream.Write( rPoly.mpImplPolygon->mpPointAry, nPoints*sizeof(Point) );
2056cdf0e10cSrcweir 		}
2057cdf0e10cSrcweir 	}
2058cdf0e10cSrcweir 
2059cdf0e10cSrcweir 	return rOStream;
2060cdf0e10cSrcweir }
2061cdf0e10cSrcweir 
2062cdf0e10cSrcweir // -----------------------------------------------------------------------
2063cdf0e10cSrcweir 
2064cdf0e10cSrcweir void Polygon::ImplRead( SvStream& rIStream )
2065cdf0e10cSrcweir {
2066cdf0e10cSrcweir 	sal_uInt8	bHasPolyFlags;
2067cdf0e10cSrcweir 
2068cdf0e10cSrcweir 	rIStream >> *this
2069cdf0e10cSrcweir 			 >> bHasPolyFlags;
2070cdf0e10cSrcweir 
2071cdf0e10cSrcweir 	if ( bHasPolyFlags )
2072cdf0e10cSrcweir 	{
2073cdf0e10cSrcweir 		mpImplPolygon->mpFlagAry = new sal_uInt8[ mpImplPolygon->mnPoints ];
2074cdf0e10cSrcweir 		rIStream.Read( mpImplPolygon->mpFlagAry, mpImplPolygon->mnPoints );
2075cdf0e10cSrcweir 	}
2076cdf0e10cSrcweir }
2077cdf0e10cSrcweir 
2078cdf0e10cSrcweir // -----------------------------------------------------------------------
2079cdf0e10cSrcweir 
2080cdf0e10cSrcweir void Polygon::Read( SvStream& rIStream )
2081cdf0e10cSrcweir {
2082cdf0e10cSrcweir 	VersionCompat aCompat( rIStream, STREAM_READ );
2083cdf0e10cSrcweir 
2084cdf0e10cSrcweir     ImplRead( rIStream );
2085cdf0e10cSrcweir }
2086cdf0e10cSrcweir 
2087cdf0e10cSrcweir // -----------------------------------------------------------------------
2088cdf0e10cSrcweir 
2089cdf0e10cSrcweir void Polygon::ImplWrite( SvStream& rOStream ) const
2090cdf0e10cSrcweir {
2091cdf0e10cSrcweir 	sal_uInt8	bHasPolyFlags = mpImplPolygon->mpFlagAry != NULL;
2092cdf0e10cSrcweir 	rOStream << *this
2093cdf0e10cSrcweir 			 << bHasPolyFlags;
2094cdf0e10cSrcweir 
2095cdf0e10cSrcweir 	if ( bHasPolyFlags )
2096cdf0e10cSrcweir 		rOStream.Write( mpImplPolygon->mpFlagAry, mpImplPolygon->mnPoints );
2097cdf0e10cSrcweir }
2098cdf0e10cSrcweir 
2099cdf0e10cSrcweir // -----------------------------------------------------------------------
2100cdf0e10cSrcweir 
2101cdf0e10cSrcweir void Polygon::Write( SvStream& rOStream ) const
2102cdf0e10cSrcweir {
2103cdf0e10cSrcweir 	VersionCompat aCompat( rOStream, STREAM_WRITE, 1 );
2104cdf0e10cSrcweir 
2105cdf0e10cSrcweir     ImplWrite( rOStream );
2106cdf0e10cSrcweir }
2107cdf0e10cSrcweir 
2108cdf0e10cSrcweir // -----------------------------------------------------------------------
2109cdf0e10cSrcweir // #i74631# numerical correction method for B2DPolygon
2110cdf0e10cSrcweir void impCorrectContinuity(basegfx::B2DPolygon& roPolygon, sal_uInt32 nIndex, sal_uInt8 nCFlag)
2111cdf0e10cSrcweir {
2112cdf0e10cSrcweir 	const sal_uInt32 nPointCount(roPolygon.count());
2113cdf0e10cSrcweir 	OSL_ENSURE(nIndex < nPointCount, "impCorrectContinuity: index access out of range (!)");
2114cdf0e10cSrcweir 
2115cdf0e10cSrcweir 	if(nIndex < nPointCount && (POLY_SMOOTH == nCFlag || POLY_SYMMTR == nCFlag))
2116cdf0e10cSrcweir 	{
2117cdf0e10cSrcweir 		if(roPolygon.isPrevControlPointUsed(nIndex) && roPolygon.isNextControlPointUsed(nIndex))
2118cdf0e10cSrcweir 		{
2119cdf0e10cSrcweir 			const basegfx::B2DPoint aPoint(roPolygon.getB2DPoint(nIndex));
2120cdf0e10cSrcweir 
2121cdf0e10cSrcweir 			if(POLY_SMOOTH == nCFlag)
2122cdf0e10cSrcweir 			{
2123cdf0e10cSrcweir 				// C1: apply inverse direction of prev to next, keep length of next
2124cdf0e10cSrcweir 				const basegfx::B2DVector aOriginalNext(roPolygon.getNextControlPoint(nIndex) - aPoint);
2125cdf0e10cSrcweir 				basegfx::B2DVector aNewNext(aPoint - roPolygon.getPrevControlPoint(nIndex));
2126cdf0e10cSrcweir 
2127cdf0e10cSrcweir 				aNewNext.setLength(aOriginalNext.getLength());
2128cdf0e10cSrcweir 				roPolygon.setNextControlPoint(nIndex, basegfx::B2DPoint(aPoint + aNewNext));
2129cdf0e10cSrcweir 			}
2130cdf0e10cSrcweir 			else // POLY_SYMMTR
2131cdf0e10cSrcweir 			{
2132cdf0e10cSrcweir 				// C2: apply inverse control point to next
2133cdf0e10cSrcweir 				roPolygon.setNextControlPoint(nIndex, (2.0 * aPoint) - roPolygon.getPrevControlPoint(nIndex));
2134cdf0e10cSrcweir 			}
2135cdf0e10cSrcweir 		}
2136cdf0e10cSrcweir 	}
2137cdf0e10cSrcweir }
2138cdf0e10cSrcweir 
2139cdf0e10cSrcweir // -----------------------------------------------------------------------
2140cdf0e10cSrcweir // convert to basegfx::B2DPolygon and return
2141cdf0e10cSrcweir basegfx::B2DPolygon Polygon::getB2DPolygon() const
2142cdf0e10cSrcweir {
2143cdf0e10cSrcweir 	basegfx::B2DPolygon aRetval;
2144cdf0e10cSrcweir 	const sal_uInt16 nCount(mpImplPolygon->mnPoints);
2145cdf0e10cSrcweir 
2146cdf0e10cSrcweir 	if(nCount)
2147cdf0e10cSrcweir 	{
2148cdf0e10cSrcweir 		if(mpImplPolygon->mpFlagAry)
2149cdf0e10cSrcweir 		{
2150cdf0e10cSrcweir 			// handling for curves. Add start point
2151cdf0e10cSrcweir 			const Point aStartPoint(mpImplPolygon->mpPointAry[0]);
2152cdf0e10cSrcweir 			sal_uInt8 nPointFlag(mpImplPolygon->mpFlagAry[0]);
2153cdf0e10cSrcweir 			aRetval.append(basegfx::B2DPoint(aStartPoint.X(), aStartPoint.Y()));
2154cdf0e10cSrcweir 			Point aControlA, aControlB;
2155cdf0e10cSrcweir 
2156cdf0e10cSrcweir 			for(sal_uInt16 a(1); a < nCount;)
2157cdf0e10cSrcweir 			{
2158cdf0e10cSrcweir 				bool bControlA(false);
2159cdf0e10cSrcweir 				bool bControlB(false);
2160cdf0e10cSrcweir 
2161cdf0e10cSrcweir 				if(POLY_CONTROL == mpImplPolygon->mpFlagAry[a])
2162cdf0e10cSrcweir 				{
2163cdf0e10cSrcweir 					aControlA = mpImplPolygon->mpPointAry[a++];
2164cdf0e10cSrcweir 					bControlA = true;
2165cdf0e10cSrcweir 				}
2166cdf0e10cSrcweir 
2167cdf0e10cSrcweir 				if(a < nCount && POLY_CONTROL == mpImplPolygon->mpFlagAry[a])
2168cdf0e10cSrcweir 				{
2169cdf0e10cSrcweir 					aControlB = mpImplPolygon->mpPointAry[a++];
2170cdf0e10cSrcweir 					bControlB = true;
2171cdf0e10cSrcweir 				}
2172cdf0e10cSrcweir 
2173cdf0e10cSrcweir 				// assert invalid polygons
2174cdf0e10cSrcweir 				OSL_ENSURE(bControlA == bControlB, "Polygon::getB2DPolygon: Invalid source polygon (!)");
2175cdf0e10cSrcweir 
2176cdf0e10cSrcweir 				if(a < nCount)
2177cdf0e10cSrcweir 				{
2178cdf0e10cSrcweir 					const Point aEndPoint(mpImplPolygon->mpPointAry[a]);
2179cdf0e10cSrcweir 
2180cdf0e10cSrcweir 					if(bControlA)
2181cdf0e10cSrcweir 					{
2182cdf0e10cSrcweir 						// bezier edge, add
2183cdf0e10cSrcweir 						aRetval.appendBezierSegment(
2184cdf0e10cSrcweir 							basegfx::B2DPoint(aControlA.X(), aControlA.Y()),
2185cdf0e10cSrcweir 							basegfx::B2DPoint(aControlB.X(), aControlB.Y()),
2186cdf0e10cSrcweir 							basegfx::B2DPoint(aEndPoint.X(), aEndPoint.Y()));
2187cdf0e10cSrcweir 
2188cdf0e10cSrcweir 						impCorrectContinuity(aRetval, aRetval.count() - 2, nPointFlag);
2189cdf0e10cSrcweir 					}
2190cdf0e10cSrcweir 					else
2191cdf0e10cSrcweir 					{
2192cdf0e10cSrcweir 						// no bezier edge, add end point
2193cdf0e10cSrcweir 						aRetval.append(basegfx::B2DPoint(aEndPoint.X(), aEndPoint.Y()));
2194cdf0e10cSrcweir 					}
2195cdf0e10cSrcweir 
2196cdf0e10cSrcweir 					nPointFlag = mpImplPolygon->mpFlagAry[a++];
2197cdf0e10cSrcweir 				}
2198cdf0e10cSrcweir 			}
2199cdf0e10cSrcweir 
2200cdf0e10cSrcweir 			// if exist, remove double first/last points, set closed and correct control points
2201cdf0e10cSrcweir 			basegfx::tools::checkClosed(aRetval);
2202cdf0e10cSrcweir 
2203cdf0e10cSrcweir 			if(aRetval.isClosed())
2204cdf0e10cSrcweir 			{
2205cdf0e10cSrcweir 				// closeWithGeometryChange did really close, so last point(s) were removed.
2206cdf0e10cSrcweir 				// Correct the continuity in the changed point
2207cdf0e10cSrcweir 				impCorrectContinuity(aRetval, 0, mpImplPolygon->mpFlagAry[0]);
2208cdf0e10cSrcweir 			}
2209cdf0e10cSrcweir 		}
2210cdf0e10cSrcweir 		else
2211cdf0e10cSrcweir 		{
2212cdf0e10cSrcweir 			// extra handling for non-curves (most-used case) for speedup
2213cdf0e10cSrcweir 			for(sal_uInt16 a(0); a < nCount; a++)
2214cdf0e10cSrcweir 			{
2215cdf0e10cSrcweir 				// get point and add
2216cdf0e10cSrcweir 				const Point aPoint(mpImplPolygon->mpPointAry[a]);
2217cdf0e10cSrcweir 				aRetval.append(basegfx::B2DPoint(aPoint.X(), aPoint.Y()));
2218cdf0e10cSrcweir 			}
2219cdf0e10cSrcweir 
2220cdf0e10cSrcweir 			// set closed flag
2221cdf0e10cSrcweir 			basegfx::tools::checkClosed(aRetval);
2222cdf0e10cSrcweir 		}
2223cdf0e10cSrcweir 	}
2224cdf0e10cSrcweir 
2225cdf0e10cSrcweir 	return aRetval;
2226cdf0e10cSrcweir }
2227cdf0e10cSrcweir 
2228cdf0e10cSrcweir // -----------------------------------------------------------------------
2229cdf0e10cSrcweir // constructor to convert from basegfx::B2DPolygon
2230cdf0e10cSrcweir // #i76891# Needed to change from adding all control points (even for unused
2231cdf0e10cSrcweir // edges) and creating a fixed-size Polygon in the first run to creating the
2232cdf0e10cSrcweir // minimal Polygon. This requires a temporary Point- and Flag-Array for curves
2233cdf0e10cSrcweir // and a memcopy at ImplPolygon creation, but contains no zero-controlpoints
2234cdf0e10cSrcweir // for straight edges.
2235cdf0e10cSrcweir Polygon::Polygon(const basegfx::B2DPolygon& rPolygon)
2236cdf0e10cSrcweir :	mpImplPolygon(0)
2237cdf0e10cSrcweir {
2238cdf0e10cSrcweir 	DBG_CTOR( Polygon, NULL );
2239cdf0e10cSrcweir 
2240cdf0e10cSrcweir 	const bool bCurve(rPolygon.areControlPointsUsed());
2241cdf0e10cSrcweir 	const bool bClosed(rPolygon.isClosed());
2242cdf0e10cSrcweir 	sal_uInt32 nB2DLocalCount(rPolygon.count());
2243cdf0e10cSrcweir 
2244cdf0e10cSrcweir 	if(bCurve)
2245cdf0e10cSrcweir 	{
2246cdf0e10cSrcweir 		// #127979# Reduce source point count hard to the limit of the tools Polygon
2247cdf0e10cSrcweir 		if(nB2DLocalCount > ((0x0000ffff / 3L) - 1L))
2248cdf0e10cSrcweir 		{
2249cdf0e10cSrcweir 			DBG_ERROR("Polygon::Polygon: Too many points in given B2DPolygon, need to reduce hard to maximum of tools Polygon (!)");
2250cdf0e10cSrcweir 			nB2DLocalCount = ((0x0000ffff / 3L) - 1L);
2251cdf0e10cSrcweir 		}
2252cdf0e10cSrcweir 
2253cdf0e10cSrcweir 		// calculate target point count
2254cdf0e10cSrcweir 		const sal_uInt32 nLoopCount(bClosed ? nB2DLocalCount : (nB2DLocalCount ? nB2DLocalCount - 1L : 0L ));
2255cdf0e10cSrcweir 
2256cdf0e10cSrcweir 		if(nLoopCount)
2257cdf0e10cSrcweir 		{
2258cdf0e10cSrcweir 			// calculate maximum array size and allocate; prepare insert index
2259cdf0e10cSrcweir 			const sal_uInt32 nMaxTargetCount((nLoopCount * 3) + 1);
2260cdf0e10cSrcweir 			mpImplPolygon = new ImplPolygon(static_cast< sal_uInt16 >(nMaxTargetCount), true);
2261cdf0e10cSrcweir 
2262cdf0e10cSrcweir 			// prepare insert index and current point
2263cdf0e10cSrcweir 			sal_uInt32 nArrayInsert(0);
2264cdf0e10cSrcweir 			basegfx::B2DCubicBezier aBezier;
2265cdf0e10cSrcweir 			aBezier.setStartPoint(rPolygon.getB2DPoint(0));
2266cdf0e10cSrcweir 
2267cdf0e10cSrcweir 			for(sal_uInt32 a(0L); a < nLoopCount; a++)
2268cdf0e10cSrcweir 			{
2269cdf0e10cSrcweir 				// add current point (always) and remember StartPointIndex for evtl. later corrections
2270cdf0e10cSrcweir 				const Point aStartPoint(FRound(aBezier.getStartPoint().getX()), FRound(aBezier.getStartPoint().getY()));
2271cdf0e10cSrcweir 				const sal_uInt32 nStartPointIndex(nArrayInsert);
2272cdf0e10cSrcweir 				mpImplPolygon->mpPointAry[nStartPointIndex] = aStartPoint;
2273cdf0e10cSrcweir 				mpImplPolygon->mpFlagAry[nStartPointIndex] = (sal_uInt8)POLY_NORMAL;
2274cdf0e10cSrcweir 				nArrayInsert++;
2275cdf0e10cSrcweir 
2276cdf0e10cSrcweir 				// prepare next segment
2277cdf0e10cSrcweir 				const sal_uInt32 nNextIndex((a + 1) % nB2DLocalCount);
2278cdf0e10cSrcweir 				aBezier.setEndPoint(rPolygon.getB2DPoint(nNextIndex));
2279cdf0e10cSrcweir 				aBezier.setControlPointA(rPolygon.getNextControlPoint(a));
2280cdf0e10cSrcweir 				aBezier.setControlPointB(rPolygon.getPrevControlPoint(nNextIndex));
2281cdf0e10cSrcweir 
2282cdf0e10cSrcweir 				if(aBezier.isBezier())
2283cdf0e10cSrcweir 				{
2284cdf0e10cSrcweir 					// if one is used, add always two control points due to the old schema
2285cdf0e10cSrcweir 					mpImplPolygon->mpPointAry[nArrayInsert] = Point(FRound(aBezier.getControlPointA().getX()), FRound(aBezier.getControlPointA().getY()));
2286cdf0e10cSrcweir 					mpImplPolygon->mpFlagAry[nArrayInsert] = (sal_uInt8)POLY_CONTROL;
2287cdf0e10cSrcweir 					nArrayInsert++;
2288cdf0e10cSrcweir 
2289cdf0e10cSrcweir 					mpImplPolygon->mpPointAry[nArrayInsert] = Point(FRound(aBezier.getControlPointB().getX()), FRound(aBezier.getControlPointB().getY()));
2290cdf0e10cSrcweir 					mpImplPolygon->mpFlagAry[nArrayInsert] = (sal_uInt8)POLY_CONTROL;
2291cdf0e10cSrcweir 					nArrayInsert++;
2292cdf0e10cSrcweir 				}
2293cdf0e10cSrcweir 
2294cdf0e10cSrcweir 				// test continuity with previous control point to set flag value
2295cdf0e10cSrcweir 				if(aBezier.getControlPointA() != aBezier.getStartPoint() && (bClosed || a))
2296cdf0e10cSrcweir 				{
2297cdf0e10cSrcweir 					const basegfx::B2VectorContinuity eCont(rPolygon.getContinuityInPoint(a));
2298cdf0e10cSrcweir 
2299cdf0e10cSrcweir 					if(basegfx::CONTINUITY_C1 == eCont)
2300cdf0e10cSrcweir 					{
2301cdf0e10cSrcweir 						mpImplPolygon->mpFlagAry[nStartPointIndex] = (sal_uInt8)POLY_SMOOTH;
2302cdf0e10cSrcweir 					}
2303cdf0e10cSrcweir 					else if(basegfx::CONTINUITY_C2 == eCont)
2304cdf0e10cSrcweir 					{
2305cdf0e10cSrcweir 						mpImplPolygon->mpFlagAry[nStartPointIndex] = (sal_uInt8)POLY_SYMMTR;
2306cdf0e10cSrcweir 					}
2307cdf0e10cSrcweir 				}
2308cdf0e10cSrcweir 
2309cdf0e10cSrcweir 				// prepare next polygon step
2310cdf0e10cSrcweir 				aBezier.setStartPoint(aBezier.getEndPoint());
2311cdf0e10cSrcweir 			}
2312cdf0e10cSrcweir 
2313cdf0e10cSrcweir 			if(bClosed)
2314cdf0e10cSrcweir 			{
2315cdf0e10cSrcweir 				// add first point again as closing point due to old definition
2316cdf0e10cSrcweir 				mpImplPolygon->mpPointAry[nArrayInsert] = mpImplPolygon->mpPointAry[0];
2317cdf0e10cSrcweir 				mpImplPolygon->mpFlagAry[nArrayInsert] = (sal_uInt8)POLY_NORMAL;
2318cdf0e10cSrcweir 				nArrayInsert++;
2319cdf0e10cSrcweir 			}
2320cdf0e10cSrcweir 			else
2321cdf0e10cSrcweir 			{
2322cdf0e10cSrcweir 				// add last point as closing point
2323cdf0e10cSrcweir 				const basegfx::B2DPoint aClosingPoint(rPolygon.getB2DPoint(nB2DLocalCount - 1L));
2324cdf0e10cSrcweir 				const Point aEnd(FRound(aClosingPoint.getX()), FRound(aClosingPoint.getY()));
2325cdf0e10cSrcweir 				mpImplPolygon->mpPointAry[nArrayInsert] = aEnd;
2326cdf0e10cSrcweir 				mpImplPolygon->mpFlagAry[nArrayInsert] = (sal_uInt8)POLY_NORMAL;
2327cdf0e10cSrcweir 				nArrayInsert++;
2328cdf0e10cSrcweir 			}
2329cdf0e10cSrcweir 
2330cdf0e10cSrcweir 			DBG_ASSERT(nArrayInsert <= nMaxTargetCount, "Polygon::Polygon from basegfx::B2DPolygon: wrong max point count estimation (!)");
2331cdf0e10cSrcweir 
2332cdf0e10cSrcweir 			if(nArrayInsert != nMaxTargetCount)
2333cdf0e10cSrcweir 			{
2334cdf0e10cSrcweir 				mpImplPolygon->ImplSetSize(static_cast< sal_uInt16 >(nArrayInsert), true);
2335cdf0e10cSrcweir 			}
2336cdf0e10cSrcweir 		}
2337cdf0e10cSrcweir 	}
2338cdf0e10cSrcweir 	else
2339cdf0e10cSrcweir 	{
2340cdf0e10cSrcweir 		// #127979# Reduce source point count hard to the limit of the tools Polygon
2341cdf0e10cSrcweir 		if(nB2DLocalCount > (0x0000ffff - 1L))
2342cdf0e10cSrcweir 		{
2343cdf0e10cSrcweir 			DBG_ERROR("Polygon::Polygon: Too many points in given B2DPolygon, need to reduce hard to maximum of tools Polygon (!)");
2344cdf0e10cSrcweir 			nB2DLocalCount = (0x0000ffff - 1L);
2345cdf0e10cSrcweir 		}
2346cdf0e10cSrcweir 
2347cdf0e10cSrcweir 		if(nB2DLocalCount)
2348cdf0e10cSrcweir 		{
2349cdf0e10cSrcweir 			// point list creation
2350cdf0e10cSrcweir 			const sal_uInt32 nTargetCount(nB2DLocalCount + (bClosed ? 1L : 0L));
2351cdf0e10cSrcweir 			mpImplPolygon = new ImplPolygon( static_cast< sal_uInt16 >(nTargetCount) );
2352cdf0e10cSrcweir 			sal_uInt16 nIndex(0);
2353cdf0e10cSrcweir 
2354cdf0e10cSrcweir 			for(sal_uInt32 a(0L); a < nB2DLocalCount; a++)
2355cdf0e10cSrcweir 			{
2356cdf0e10cSrcweir 				basegfx::B2DPoint aB2DPoint(rPolygon.getB2DPoint(a));
2357cdf0e10cSrcweir 				Point aPoint(FRound(aB2DPoint.getX()), FRound(aB2DPoint.getY()));
2358cdf0e10cSrcweir 				mpImplPolygon->mpPointAry[nIndex++] = aPoint;
2359cdf0e10cSrcweir 			}
2360cdf0e10cSrcweir 
2361cdf0e10cSrcweir 			if(bClosed)
2362cdf0e10cSrcweir 			{
2363cdf0e10cSrcweir 				// add first point as closing point
2364cdf0e10cSrcweir 				mpImplPolygon->mpPointAry[nIndex] = mpImplPolygon->mpPointAry[0];
2365cdf0e10cSrcweir 			}
2366cdf0e10cSrcweir 		}
2367cdf0e10cSrcweir 	}
2368cdf0e10cSrcweir 
2369cdf0e10cSrcweir 	if(!mpImplPolygon)
2370cdf0e10cSrcweir 	{
2371cdf0e10cSrcweir 		// no content yet, create empty polygon
2372cdf0e10cSrcweir 		mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon);
2373cdf0e10cSrcweir 	}
2374cdf0e10cSrcweir }
2375cdf0e10cSrcweir 
2376cdf0e10cSrcweir // eof
2377