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