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