xref: /AOO42X/main/tools/source/generic/poly.cxx (revision b1c5455db1639c48e26c568e4fa7ee78ca5d60ee)
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
10cdf0e10cSrcweir  *
1189b56da7SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
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.
19cdf0e10cSrcweir  *
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();
6394cc34ec4Smseidel     const double    fX2 = 3.0 * rCtrlPt2.X();
6404cc34ec4Smseidel     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++ ];
1079215e5487SJürgen Schmidt 
1080215e5487SJürgen Schmidt             if (aPoints.size() >= SAL_MAX_UINT16)
1081215e5487SJürgen Schmidt             {
1082215e5487SJürgen Schmidt                 OSL_ENSURE(aPoints.size() < SAL_MAX_UINT16,
1083215e5487SJürgen Schmidt                     "Polygon::AdapativeSubdivision created polygon too many points;"
1084215e5487SJürgen Schmidt                     " using original polygon instead");
1085215e5487SJürgen Schmidt 
1086215e5487SJürgen Schmidt                 // The resulting polygon can not hold all the points
1087215e5487SJürgen Schmidt                 // that we have created so far.  Stop the subdivision
1088215e5487SJürgen Schmidt                 // and return a copy of the unmodified polygon.
1089215e5487SJürgen Schmidt                 rResult = *this;
1090215e5487SJürgen Schmidt                 return;
1091215e5487SJü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 {
18714cc34ec4Smseidel     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         {
2132*4e18f706SJohn Bampton             // #115917# Patch from osnola (modified, thanks for showing the problem)
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