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