xref: /AOO41X/main/svx/source/xoutdev/_xpoly.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svx.hxx"
30 #include <osl/endian.h>
31 #include <tools/stream.hxx>
32 #include <tools/debug.hxx>
33 #include <tools/poly.hxx>
34 
35 #include <svx/xpoly.hxx>
36 #include "xpolyimp.hxx"
37 #include <basegfx/polygon/b2dpolygon.hxx>
38 #include <basegfx/point/b2dpoint.hxx>
39 #include <basegfx/vector/b2dvector.hxx>
40 #include <basegfx/polygon/b2dpolygontools.hxx>
41 #include <vcl/salbtype.hxx>		// FRound
42 #include <basegfx/range/b2drange.hxx>
43 #include <basegfx/numeric/ftools.hxx>
44 
45 #define GLOBALOVERFLOW
46 
47 DBG_NAME(XPolygon);
48 DBG_NAME(XPolyPolygon);
49 
50 /*************************************************************************
51 |*
52 |*    ImpXPolygon::ImpXPolygon()
53 |*
54 |*    Beschreibung
55 |*    Ersterstellung    08.11.94
56 |*    Letzte Aenderung  12.01.95 ESO
57 |*
58 *************************************************************************/
59 
60 ImpXPolygon::ImpXPolygon( sal_uInt16 nInitSize, sal_uInt16 _nResize )
61 {
62 	pPointAry               = NULL;
63 	pFlagAry                = NULL;
64 	bDeleteOldPoints        = sal_False;
65 	nSize                   = 0;
66 	nResize					= _nResize;
67 	nPoints                 = 0;
68 	nRefCount               = 1;
69 
70 	Resize( nInitSize );
71 }
72 
73 /*************************************************************************
74 |*
75 |*    ImpXPolygon::ImpXPolygon()
76 |*
77 |*    Beschreibung
78 |*    Ersterstellung    08.11.94
79 |*    Letzte Aenderung  12.01.95 ESO
80 |*
81 *************************************************************************/
82 
83 ImpXPolygon::ImpXPolygon( const ImpXPolygon& rImpXPoly )
84 {
85 	( (ImpXPolygon&) rImpXPoly ).CheckPointDelete();
86 
87 	pPointAry               = NULL;
88 	pFlagAry                = NULL;
89 	bDeleteOldPoints        = sal_False;
90 	nSize                   = 0;
91 	ImpXPolygon::nResize    = rImpXPoly.nResize;
92 	nPoints                 = 0;
93 	nRefCount               = 1;
94 
95 	Resize( rImpXPoly.nSize );
96 
97 	// Kopieren
98 	nPoints = rImpXPoly.nPoints;
99 	memcpy( pPointAry, rImpXPoly.pPointAry, nSize*sizeof( Point ) );
100 	memcpy( pFlagAry, rImpXPoly.pFlagAry, nSize );
101 }
102 
103 /*************************************************************************
104 |*
105 |*    ImpXPolygon::~ImpXPolygon()
106 |*
107 |*    Beschreibung
108 |*    Ersterstellung    08.11.94
109 |*    Letzte Aenderung  12.01.95 ESO
110 |*
111 *************************************************************************/
112 
113 ImpXPolygon::~ImpXPolygon()
114 {
115 	delete[] (char*) pPointAry;
116 	delete[] pFlagAry;
117 	if ( bDeleteOldPoints )
118 		delete[] (char*) pOldPointAry;
119 }
120 
121 /*************************************************************************
122 |*
123 |*    ImpXPolygon::operator==()
124 |*
125 |*    Ersterstellung    Joe 26-09-95
126 |*    Letzte Aenderung
127 |*
128 *************************************************************************/
129 
130 
131 bool ImpXPolygon::operator==(const ImpXPolygon& rImpXPoly) const
132 {
133 	return nPoints==rImpXPoly.nPoints &&
134 		   (nPoints==0 ||
135 			(memcmp(pPointAry,rImpXPoly.pPointAry,nPoints*sizeof(Point))==0 &&
136 			 memcmp(pFlagAry,rImpXPoly.pFlagAry,nPoints)==0));
137 }
138 
139 /*************************************************************************
140 |*
141 |*    ImpXPolygon::Resize()
142 |*
143 |*    !!! Polygongroesse aendern - wenn bDeletePoints sal_False, dann den
144 |*    Point-Array nicht loeschen, sondern in pOldPointAry sichern und
145 |*    das Flag bDeleteOldPoints setzen. Beim naechsten Zugriff wird
146 |*    das Array dann geloescht.
147 |*    Damit wird verhindert, dass bei XPoly[n] = XPoly[0] durch ein
148 |*    Resize der fuer den rechten Ausdruck verwendete Point-Array
149 |*    vorzeitig geloescht wird.
150 |*    Ersterstellung    08.11.94
151 |*    Letzte Aenderung  12.01.95 ESO
152 |*
153 *************************************************************************/
154 
155 void ImpXPolygon::Resize( sal_uInt16 nNewSize, sal_Bool bDeletePoints )
156 {
157 	if( nNewSize == nSize )
158 		return;
159 
160 	sal_uInt8*   pOldFlagAry  = pFlagAry;
161 	sal_uInt16  nOldSize     = nSize;
162 
163 	CheckPointDelete();
164 	pOldPointAry = pPointAry;
165 
166 	// Neue Groesse auf vielfaches von nResize runden, sofern Objekt
167 	// nicht neu angelegt wurde (nSize != 0)
168 	if ( nSize != 0 && nNewSize > nSize )
169 	{
170 		DBG_ASSERT(nResize, "Resize-Versuch trotz nResize = 0 !");
171 		nNewSize = nSize + ((nNewSize-nSize-1) / nResize + 1) * nResize;
172 	}
173 	// Punkt Array erzeugen
174 	nSize     = nNewSize;
175 	pPointAry = (Point*)new char[ nSize*sizeof( Point ) ];
176 	memset( pPointAry, 0, nSize*sizeof( Point ) );
177 
178 	// Flag Array erzeugen
179 	pFlagAry = new sal_uInt8[ nSize ];
180 	memset( pFlagAry, 0, nSize );
181 
182 	// Eventuell umkopieren
183 	if( nOldSize )
184 	{
185 		if( nOldSize < nSize )
186 		{
187 			memcpy( pPointAry, pOldPointAry, nOldSize*sizeof( Point ) );
188 			memcpy( pFlagAry,  pOldFlagAry, nOldSize );
189 		}
190 		else
191 		{
192 			memcpy( pPointAry, pOldPointAry, nSize*sizeof( Point ) );
193 			memcpy( pFlagAry, pOldFlagAry, nSize );
194 
195 			// Anzahl der gueltigen Punkte anpassen
196 			if( nPoints > nSize )
197 				nPoints = nSize;
198 		}
199 		if ( bDeletePoints )    delete[] (char*) pOldPointAry;
200 		else                    bDeleteOldPoints = sal_True;
201 		delete[] pOldFlagAry;
202 	}
203 }
204 
205 
206 /*************************************************************************
207 |*
208 |*    ImpXPolygon::InsertSpace()
209 |*
210 |*    Beschreibung
211 |*    Ersterstellung    08.11.94
212 |*    Letzte Aenderung  29.03.95 ESO
213 |*
214 *************************************************************************/
215 
216 void ImpXPolygon::InsertSpace( sal_uInt16 nPos, sal_uInt16 nCount )
217 {
218 	CheckPointDelete();
219 
220 	if ( nPos > nPoints )
221 		nPos = nPoints;
222 
223 	// Wenn Polygon zu klein dann groesser machen
224 	if( (nPoints + nCount) > nSize )
225 		Resize( nPoints + nCount );
226 
227 	// Wenn nicht hinter dem letzten Punkt eingefuegt wurde,
228 	// den Rest nach hinten schieben
229 	if( nPos < nPoints )
230 	{
231 		sal_uInt16 nMove = nPoints - nPos;
232 		memmove( &pPointAry[nPos+nCount], &pPointAry[nPos],
233 				 nMove * sizeof(Point) );
234 		memmove( &pFlagAry[nPos+nCount], &pFlagAry[nPos], nMove );
235 	}
236 	memset( &pPointAry[nPos], 0, nCount * sizeof( Point ) );
237 	memset( &pFlagAry [nPos], 0, nCount );
238 
239 	nPoints = nPoints + nCount;
240 }
241 
242 
243 /*************************************************************************
244 |*
245 |*    ImpXPolygon::Remove()
246 |*
247 |*    Beschreibung
248 |*    Ersterstellung    08.11.94
249 |*    Letzte Aenderung  12.01.94 ESO
250 |*
251 *************************************************************************/
252 
253 void ImpXPolygon::Remove( sal_uInt16 nPos, sal_uInt16 nCount )
254 {
255 	CheckPointDelete();
256 
257 	if( (nPos + nCount) <= nPoints )
258 	{
259 		sal_uInt16 nMove = nPoints - nPos - nCount;
260 
261 		if( nMove )
262 		{
263 			memmove( &pPointAry[nPos], &pPointAry[nPos+nCount],
264 					 nMove * sizeof(Point) );
265 			memmove( &pFlagAry[nPos], &pFlagAry[nPos+nCount], nMove );
266 		}
267 		memset( &pPointAry[nPoints - nCount], 0, nCount * sizeof( Point ) );
268 		memset( &pFlagAry [nPoints - nCount], 0, nCount );
269 		nPoints = nPoints - nCount;
270 	}
271 }
272 
273 
274 /*************************************************************************
275 |*
276 |*    XPolygon::XPolygon()
277 |*
278 |*    Beschreibung
279 |*    Ersterstellung    08.11.94
280 |*    Letzte Aenderung  08.11.94
281 |*
282 *************************************************************************/
283 
284 XPolygon::XPolygon( sal_uInt16 nSize, sal_uInt16 nResize )
285 {
286 	DBG_CTOR(XPolygon,NULL);
287 	pImpXPolygon = new ImpXPolygon( nSize, nResize );
288 }
289 
290 /*************************************************************************
291 |*
292 |*    XPolygon::XPolygon()
293 |*
294 |*    Beschreibung
295 |*    Ersterstellung    08.11.94
296 |*    Letzte Aenderung  08.11.94
297 |*
298 *************************************************************************/
299 
300 XPolygon::XPolygon( const XPolygon& rXPoly )
301 {
302 	DBG_CTOR(XPolygon,NULL);
303 	pImpXPolygon = rXPoly.pImpXPolygon;
304 	pImpXPolygon->nRefCount++;
305 }
306 
307 /*************************************************************************
308 |*
309 |*    XPolygon::XPolygon()
310 |*
311 |*    XPolygon aus einem Standardpolygon erstellen
312 |*    Ersterstellung    18.01.95 ESO
313 |*    Letzte Aenderung  18.01.95 ESO
314 |*
315 *************************************************************************/
316 
317 XPolygon::XPolygon( const Polygon& rPoly )
318 {
319 	DBG_CTOR(XPolygon,NULL);
320 
321 	sal_uInt16 nSize = rPoly.GetSize();
322 	pImpXPolygon = new ImpXPolygon( nSize );
323 	pImpXPolygon->nPoints = nSize;
324 
325 	for( sal_uInt16 i = 0; i < nSize;  i++ )
326 	{
327 		pImpXPolygon->pPointAry[i] = rPoly[i];
328 		pImpXPolygon->pFlagAry[i] = (sal_uInt8) rPoly.GetFlags( i );
329 	}
330 }
331 
332 /*************************************************************************
333 |*
334 |*    XPolygon::XPolygon()
335 |*
336 |*    Rechteck (auch mit abgerundeten Ecken) als Bezierpolygon erzeugen
337 |*    Ersterstellung    09.01.95 ESO
338 |*    Letzte Aenderung  09.01.95 ESO
339 |*
340 *************************************************************************/
341 
342 XPolygon::XPolygon(const Rectangle& rRect, long nRx, long nRy)
343 {
344 	DBG_CTOR(XPolygon,NULL);
345 	pImpXPolygon = new ImpXPolygon(17);
346 	long nWh = (rRect.GetWidth()  - 1) / 2;
347 	long nHh = (rRect.GetHeight() - 1) / 2;
348 
349 	if ( nRx > nWh )    nRx = nWh;
350 	if ( nRy > nHh )    nRy = nHh;
351 
352 	// Rx negativ, damit Umlauf im Uhrzeigersinn erfolgt
353 	nRx = -nRx;
354 
355 	// Faktor fuer Kontrollpunkte der Bezierkurven: 8/3 * (sin(45g) - 0.5)
356 	long    nXHdl = (long)(0.552284749 * nRx);
357 	long    nYHdl = (long)(0.552284749 * nRy);
358 	sal_uInt16  nPos = 0;
359 
360 	if ( nRx && nRy )
361 	{
362 		Point aCenter;
363 
364 		for (sal_uInt16 nQuad = 0; nQuad < 4; nQuad++)
365 		{
366 			switch ( nQuad )
367 			{
368 				case 0:	aCenter = rRect.TopLeft();
369 						aCenter.X() -= nRx;
370 						aCenter.Y() += nRy;
371 						break;
372 				case 1:	aCenter = rRect.TopRight();
373 						aCenter.X() += nRx;
374 						aCenter.Y() += nRy;
375 						break;
376 				case 2:	aCenter = rRect.BottomRight();
377 						aCenter.X() += nRx;
378 						aCenter.Y() -= nRy;
379 						break;
380 				case 3:	aCenter = rRect.BottomLeft();
381 						aCenter.X() -= nRx;
382 						aCenter.Y() -= nRy;
383 						break;
384 			}
385 			GenBezArc(aCenter, nRx, nRy, nXHdl, nYHdl, 0, 900, nQuad, nPos);
386 			pImpXPolygon->pFlagAry[nPos  ] = (sal_uInt8) XPOLY_SMOOTH;
387 			pImpXPolygon->pFlagAry[nPos+3] = (sal_uInt8) XPOLY_SMOOTH;
388 			nPos += 4;
389 		}
390 	}
391 	else
392 	{
393 		pImpXPolygon->pPointAry[nPos++] = rRect.TopLeft();
394 		pImpXPolygon->pPointAry[nPos++] = rRect.TopRight();
395 		pImpXPolygon->pPointAry[nPos++] = rRect.BottomRight();
396 		pImpXPolygon->pPointAry[nPos++] = rRect.BottomLeft();
397 	}
398 	pImpXPolygon->pPointAry[nPos] = pImpXPolygon->pPointAry[0];
399 	pImpXPolygon->nPoints = nPos + 1;
400 }
401 
402 /*************************************************************************
403 |*
404 |*    XPolygon::XPolygon()
405 |*
406 |*    Ellipsen(bogen) als Bezierpolygon erzeugen
407 |*    Ersterstellung    09.01.95
408 |*    Letzte Aenderung  09.01.95
409 |*
410 *************************************************************************/
411 
412 XPolygon::XPolygon(const Point& rCenter, long nRx, long nRy,
413 				   sal_uInt16 nStartAngle, sal_uInt16 nEndAngle, sal_Bool bClose)
414 {
415 	DBG_CTOR(XPolygon,NULL);
416 	pImpXPolygon = new ImpXPolygon(17);
417 
418 	nStartAngle %= 3600;
419 	if ( nEndAngle > 3600 ) nEndAngle %= 3600;
420 	sal_Bool bFull = (nStartAngle == 0 && nEndAngle == 3600);
421 
422 	// Faktor fuer Kontrollpunkte der Bezierkurven: 8/3 * (sin(45g) - 0.5)
423 	long    nXHdl = (long)(0.552284749 * nRx);
424 	long    nYHdl = (long)(0.552284749 * nRy);
425 	sal_uInt16  nPos = 0;
426 	sal_Bool    bLoopEnd = sal_False;
427 
428 	do
429 	{
430 		sal_uInt16 nA1, nA2;
431 		sal_uInt16 nQuad = nStartAngle / 900;
432 		if ( nQuad == 4 ) nQuad = 0;
433 		bLoopEnd = CheckAngles(nStartAngle, nEndAngle, nA1, nA2);
434 		GenBezArc(rCenter, nRx, nRy, nXHdl, nYHdl, nA1, nA2, nQuad, nPos);
435 		nPos += 3;
436 		if ( !bLoopEnd )
437 			pImpXPolygon->pFlagAry[nPos] = (sal_uInt8) XPOLY_SMOOTH;
438 
439 	} while ( !bLoopEnd );
440 
441 	// Wenn kein Vollkreis, dann ggf. Enden mit Mittelpunkt verbinden
442 	if ( !bFull && bClose )
443 		pImpXPolygon->pPointAry[++nPos] = rCenter;
444 
445 	if ( bFull )
446 	{
447 		pImpXPolygon->pFlagAry[0   ] = (sal_uInt8) XPOLY_SMOOTH;
448 		pImpXPolygon->pFlagAry[nPos] = (sal_uInt8) XPOLY_SMOOTH;
449 	}
450 	pImpXPolygon->nPoints = nPos + 1;
451 }
452 
453 /*************************************************************************
454 |*
455 |*    XPolygon::~XPolygon()
456 |*
457 |*    Beschreibung
458 |*    Ersterstellung    08.11.94
459 |*    Letzte Aenderung  08.11.94
460 |*
461 *************************************************************************/
462 
463 XPolygon::~XPolygon()
464 {
465 	DBG_DTOR(XPolygon,NULL);
466 	if( pImpXPolygon->nRefCount > 1 )
467 		pImpXPolygon->nRefCount--;
468 	else
469 		delete pImpXPolygon;
470 }
471 
472 /*************************************************************************
473 |*
474 |*    XPolygon::CheckReference()
475 |*
476 |*    Referenzzaehler desImpXPoly pruefen und ggf. von diesem abkoppeln
477 |*    Ersterstellung    17.01.95 ESO
478 |*    Letzte Aenderung  17.01.95 ESO
479 |*
480 *************************************************************************/
481 
482 void XPolygon::CheckReference()
483 {
484 	if( pImpXPolygon->nRefCount > 1 )
485 	{
486 		pImpXPolygon->nRefCount--;
487 		pImpXPolygon = new ImpXPolygon( *pImpXPolygon );
488 	}
489 }
490 
491 /*************************************************************************
492 |*
493 |*    XPolygon::SetSize()
494 |*
495 |*    Beschreibung
496 |*    Ersterstellung    08.11.94
497 |*    Letzte Aenderung  08.11.94
498 |*
499 *************************************************************************/
500 
501 void XPolygon::SetSize( sal_uInt16 nNewSize )
502 {
503 	CheckReference();
504 	pImpXPolygon->Resize( nNewSize );
505 }
506 
507 /*************************************************************************
508 |*
509 |*    XPolygon::GetSize()
510 |*
511 |*    Beschreibung
512 |*    Ersterstellung    08.11.94
513 |*    Letzte Aenderung  12.01.95 ESO
514 |*
515 *************************************************************************/
516 
517 sal_uInt16 XPolygon::GetSize() const
518 {
519 	pImpXPolygon->CheckPointDelete();
520 	return pImpXPolygon->nSize;
521 }
522 
523 /*************************************************************************
524 |*
525 |*    XPolygon::SetPointCount()
526 |*
527 |*    Beschreibung
528 |*    Ersterstellung    08.11.94
529 |*    Letzte Aenderung  12.01.95 ESO
530 |*
531 *************************************************************************/
532 
533 void XPolygon::SetPointCount( sal_uInt16 nPoints )
534 {
535 	pImpXPolygon->CheckPointDelete();
536 	CheckReference();
537 
538 	if( pImpXPolygon->nSize < nPoints )
539 		pImpXPolygon->Resize( nPoints );
540 
541 	if ( nPoints < pImpXPolygon->nPoints )
542 	{
543 		sal_uInt16 nSize = pImpXPolygon->nPoints - nPoints;
544 		memset( &pImpXPolygon->pPointAry[nPoints], 0, nSize * sizeof( Point ) );
545 		memset( &pImpXPolygon->pFlagAry [nPoints], 0, nSize );
546 	}
547 	pImpXPolygon->nPoints = nPoints;
548 }
549 
550 /*************************************************************************
551 |*
552 |*    XPolygon::GetPointCount()
553 |*
554 |*    Beschreibung
555 |*    Ersterstellung    08.11.94
556 |*    Letzte Aenderung  12.01.95 ESO
557 |*
558 *************************************************************************/
559 
560 sal_uInt16 XPolygon::GetPointCount() const
561 {
562 	pImpXPolygon->CheckPointDelete();
563 	return pImpXPolygon->nPoints;
564 }
565 
566 /*************************************************************************
567 |*
568 |*    XPolygon::Insert()
569 |*
570 |*    Beschreibung
571 |*    Ersterstellung    08.11.94
572 |*    Letzte Aenderung  08.11.94
573 |*
574 *************************************************************************/
575 
576 void XPolygon::Insert( sal_uInt16 nPos, const Point& rPt, XPolyFlags eFlags )
577 {
578 	CheckReference();
579 	if (nPos>pImpXPolygon->nPoints) nPos=pImpXPolygon->nPoints;
580 	pImpXPolygon->InsertSpace( nPos, 1 );
581 	pImpXPolygon->pPointAry[nPos] = rPt;
582 	pImpXPolygon->pFlagAry[nPos]  = (sal_uInt8)eFlags;
583 }
584 
585 /*************************************************************************
586 |*
587 |*    XPolygon::Insert()
588 |*
589 |*    Beschreibung
590 |*    Ersterstellung    08.11.94
591 |*    Letzte Aenderung  08.11.94
592 |*
593 *************************************************************************/
594 
595 void XPolygon::Insert( sal_uInt16 nPos, const XPolygon& rXPoly )
596 {
597 	CheckReference();
598 	if (nPos>pImpXPolygon->nPoints) nPos=pImpXPolygon->nPoints;
599 
600 	sal_uInt16 nPoints = rXPoly.GetPointCount();
601 
602 	pImpXPolygon->InsertSpace( nPos, nPoints );
603 
604 	memcpy( &(pImpXPolygon->pPointAry[nPos]),
605 			rXPoly.pImpXPolygon->pPointAry,
606 			nPoints*sizeof( Point ) );
607 	memcpy( &(pImpXPolygon->pFlagAry[nPos]),
608 			rXPoly.pImpXPolygon->pFlagAry,
609 			nPoints );
610 }
611 
612 /*************************************************************************
613 |*
614 |*    XPolygon::Insert()
615 |*
616 |*    Beschreibung
617 |*    Ersterstellung    08.11.94
618 |*    Letzte Aenderung  08.11.94
619 |*
620 *************************************************************************/
621 
622 void XPolygon::Insert( sal_uInt16 nPos, const Polygon& rPoly )
623 {
624 	CheckReference();
625 	if (nPos>pImpXPolygon->nPoints) nPos=pImpXPolygon->nPoints;
626 
627 	sal_uInt16 nPoints = rPoly.GetSize();
628 
629 	pImpXPolygon->InsertSpace( nPos, nPoints );
630 
631 	sal_uInt16 i;
632 	for( i=0; i < nPoints; i++ )
633 		pImpXPolygon->pPointAry[i] = rPoly[i];
634 
635 	// Die Flags sind durch das InsertSpace bereits auf 0 gesetzt
636 }
637 
638 /*************************************************************************
639 |*
640 |*    XPolygon::Remove()
641 |*
642 |*    Beschreibung
643 |*    Ersterstellung    08.11.94
644 |*    Letzte Aenderung  08.11.94
645 |*
646 *************************************************************************/
647 
648 void XPolygon::Remove( sal_uInt16 nPos, sal_uInt16 nCount )
649 {
650 	CheckReference();
651 	pImpXPolygon->Remove( nPos, nCount );
652 }
653 
654 /*************************************************************************
655 |*
656 |*    XPolygon::Move()
657 |*
658 |*    Beschreibung
659 |*    Ersterstellung    09.11.94
660 |*    Letzte Aenderung  09.11.94
661 |*
662 *************************************************************************/
663 
664 void XPolygon::Move( long nHorzMove, long nVertMove )
665 {
666 	if ( !nHorzMove && !nVertMove )
667 		return;
668 
669 	CheckReference();
670 
671 	// Punkte verschieben
672 	sal_uInt16 nCount = pImpXPolygon->nPoints;
673 	for ( sal_uInt16 i = 0; i < nCount; i++ )
674 	{
675 		Point* pPt = &(pImpXPolygon->pPointAry[i]);
676 		pPt->X() += nHorzMove;
677 		pPt->Y() += nVertMove;
678 	}
679 }
680 
681 /*************************************************************************
682 |*
683 |*    XPolygon::GetBoundRect()
684 |*
685 |*    Beschreibung
686 |*    Ersterstellung    09.11.94
687 |*    Letzte Aenderung  12.01.95 ESO
688 |*
689 *************************************************************************/
690 
691 Rectangle XPolygon::GetBoundRect() const
692 {
693 	pImpXPolygon->CheckPointDelete();
694 	Rectangle aRetval;
695 
696 	if(pImpXPolygon->nPoints)
697 	{
698 		// #i37709#
699 		// For historical reasons the control points are not part of the
700 		// BoundRect. This makes it necessary to subdivide the polygon to
701 		// get a relatively correct BoundRect. Numerically, this is not
702 		// correct and never was.
703 
704 		const basegfx::B2DRange aPolygonRange(basegfx::tools::getRange(getB2DPolygon()));
705 		aRetval = Rectangle(
706 			FRound(aPolygonRange.getMinX()), FRound(aPolygonRange.getMinY()),
707 			FRound(aPolygonRange.getMaxX()), FRound(aPolygonRange.getMaxY()));
708 	}
709 
710 	return aRetval;
711 }
712 
713 /*************************************************************************
714 |*
715 |*    XPolygon::operator[]()
716 |*
717 |*    Beschreibung
718 |*    Ersterstellung    08.11.94
719 |*    Letzte Aenderung  12.01.95
720 |*
721 *************************************************************************/
722 
723 const Point& XPolygon::operator[]( sal_uInt16 nPos ) const
724 {
725 	DBG_ASSERT(nPos < pImpXPolygon->nPoints, "Ungueltiger Index bei const-Arrayzugriff auf XPolygon");
726 
727 	pImpXPolygon->CheckPointDelete();
728 	return pImpXPolygon->pPointAry[nPos];
729 }
730 
731 /*************************************************************************
732 |*
733 |*    XPolygon::operator[]()
734 |*
735 |*    Beschreibung
736 |*    Ersterstellung    08.11.94
737 |*    Letzte Aenderung  12.01.95 ESO
738 |*
739 *************************************************************************/
740 
741 Point& XPolygon::operator[]( sal_uInt16 nPos )
742 {
743 	pImpXPolygon->CheckPointDelete();
744 	CheckReference();
745 
746 	if( nPos >= pImpXPolygon->nSize )
747 	{
748 		DBG_ASSERT(pImpXPolygon->nResize, "Ungueltiger Index bei Arrayzugriff auf XPolygon");
749 		pImpXPolygon->Resize(nPos + 1, sal_False);
750 	}
751 	if( nPos >= pImpXPolygon->nPoints )
752 		pImpXPolygon->nPoints = nPos + 1;
753 
754 	return pImpXPolygon->pPointAry[nPos];
755 }
756 
757 /*************************************************************************
758 |*
759 |*    XPolygon::operator=()
760 |*
761 |*    Beschreibung      Zuweisungsoperator
762 |*    Ersterstellung    ESO 22.11.94
763 |*    Letzte Aenderung  ESO 12.01.95
764 |*
765 *************************************************************************/
766 
767 XPolygon& XPolygon::operator=( const XPolygon& rXPoly )
768 {
769 	pImpXPolygon->CheckPointDelete();
770 
771 	rXPoly.pImpXPolygon->nRefCount++;
772 
773 	if( pImpXPolygon->nRefCount > 1 )
774 		pImpXPolygon->nRefCount--;
775 	else
776 		delete pImpXPolygon;
777 
778 	pImpXPolygon = rXPoly.pImpXPolygon;
779 	return *this;
780 }
781 
782 /*************************************************************************
783 |*
784 |*    XPolygon::operator==()
785 |*
786 |*    Beschreibung      Gleichheitsoperator
787 |*    Ersterstellung    ESO 22.11.94
788 |*    Letzte Aenderung  Joe 26.09.95
789 |*
790 *************************************************************************/
791 
792 sal_Bool XPolygon::operator==( const XPolygon& rXPoly ) const
793 {
794 	pImpXPolygon->CheckPointDelete();
795 	if (rXPoly.pImpXPolygon==pImpXPolygon) return sal_True;
796 	return *rXPoly.pImpXPolygon == *pImpXPolygon;
797 }
798 
799 /*************************************************************************
800 |*
801 |*    XPolygon::operator!=()
802 |*
803 |*    Beschreibung      Ungleichheitsoperator
804 |*    Ersterstellung    ESO 22.11.94
805 |*    Letzte Aenderung  Joe 26.09.95
806 |*
807 *************************************************************************/
808 
809 sal_Bool XPolygon::operator!=( const XPolygon& rXPoly ) const
810 {
811 	pImpXPolygon->CheckPointDelete();
812 	if (rXPoly.pImpXPolygon==pImpXPolygon) return sal_False;
813 	return *rXPoly.pImpXPolygon != *pImpXPolygon;
814 }
815 
816 /*************************************************************************
817 |*
818 |*    XPolygon::GetFlags()
819 |*
820 |*    Flags fuer den Punkt an der Position nPos zurueckgeben
821 |*    Ersterstellung    ESO 11.11.94
822 |*    Letzte Aenderung  ESO 12.01.95
823 |*
824 *************************************************************************/
825 
826 XPolyFlags XPolygon::GetFlags( sal_uInt16 nPos ) const
827 {
828 	pImpXPolygon->CheckPointDelete();
829 	return (XPolyFlags) pImpXPolygon->pFlagAry[nPos];
830 }
831 
832 /*************************************************************************
833 |*
834 |*    XPolygon::SetFlags()
835 |*
836 |*    Flags fuer den Punkt an der Position nPos setzen
837 |*    Ersterstellung    ESO 11.11.94
838 |*    Letzte Aenderung  ESO 12.01.95
839 |*
840 *************************************************************************/
841 
842 void XPolygon::SetFlags( sal_uInt16 nPos, XPolyFlags eFlags )
843 {
844 	pImpXPolygon->CheckPointDelete();
845 	CheckReference();
846 	pImpXPolygon->pFlagAry[nPos] = (sal_uInt8) eFlags;
847 }
848 
849 /*************************************************************************
850 |*
851 |*    XPolygon::IsControl()
852 |*
853 |*    Kurzform zur Abfrage des CONTROL-Flags
854 |*    Ersterstellung    ESO 09.01.95
855 |*    Letzte Aenderung  ESO 12.01.95
856 |*
857 *************************************************************************/
858 
859 sal_Bool XPolygon::IsControl(sal_uInt16 nPos) const
860 {
861 	return ( (XPolyFlags) pImpXPolygon->pFlagAry[nPos] == XPOLY_CONTROL );
862 }
863 
864 /*************************************************************************
865 |*
866 |*    XPolygon::IsSmooth()
867 |*
868 |*    Kurzform zur Abfrage von SMOOTH- und SYMMTR-Flag
869 |*    Ersterstellung    ESO 18.04.95
870 |*    Letzte Aenderung  ESO 18.04.95
871 |*
872 *************************************************************************/
873 
874 sal_Bool XPolygon::IsSmooth(sal_uInt16 nPos) const
875 {
876 	XPolyFlags eFlag = (XPolyFlags) pImpXPolygon->pFlagAry[nPos];
877 	return ( eFlag == XPOLY_SMOOTH || eFlag == XPOLY_SYMMTR );
878 }
879 
880 /*************************************************************************
881 |*
882 |*    XPolygon::CalcDistance()
883 |*
884 |*    Abstand zwischen zwei Punkten berechnen
885 |*    Ersterstellung    ESO 09.01.95
886 |*    Letzte Aenderung  ESO 09.01.95
887 |*
888 *************************************************************************/
889 
890 double XPolygon::CalcDistance(sal_uInt16 nP1, sal_uInt16 nP2)
891 {
892 	const Point& rP1 = pImpXPolygon->pPointAry[nP1];
893 	const Point& rP2 = pImpXPolygon->pPointAry[nP2];
894 	double fDx = rP2.X() - rP1.X();
895 	double fDy = rP2.Y() - rP1.Y();
896 	return sqrt(fDx * fDx + fDy * fDy);
897 }
898 
899 /*************************************************************************
900 |*
901 |*    XPolygon::SubdivideBezier()
902 |*
903 |*    Bezierkurve unterteilen
904 |*    Ersterstellung    ESO 09.01.95
905 |*    Letzte Aenderung  ESO 09.01.95
906 |*
907 *************************************************************************/
908 
909 void XPolygon::SubdivideBezier(sal_uInt16 nPos, sal_Bool bCalcFirst, double fT)
910 {
911 	Point*  pPoints = pImpXPolygon->pPointAry;
912 	double  fT2 = fT * fT;
913 	double  fT3 = fT * fT2;
914 	double  fU = 1.0 - fT;
915 	double  fU2 = fU * fU;
916 	double  fU3 = fU * fU2;
917 	sal_uInt16  nIdx = nPos;
918 	short   nPosInc, nIdxInc;
919 
920 	if ( bCalcFirst )
921 	{
922 		nPos += 3;
923 		nPosInc = -1;
924 		nIdxInc = 0;
925 	}
926 	else
927 	{
928 		nPosInc = 1;
929 		nIdxInc = 1;
930 	}
931 	pPoints[nPos].X() = (long) (fU3 *       pPoints[nIdx  ].X() +
932 								fT  * fU2 * pPoints[nIdx+1].X() * 3 +
933 								fT2 * fU  * pPoints[nIdx+2].X() * 3 +
934 								fT3 *       pPoints[nIdx+3].X());
935 	pPoints[nPos].Y() = (long) (fU3 *       pPoints[nIdx  ].Y() +
936 								fT  * fU2 * pPoints[nIdx+1].Y() * 3 +
937 								fT2 * fU  * pPoints[nIdx+2].Y() * 3 +
938 								fT3 *       pPoints[nIdx+3].Y());
939 	nPos = nPos + nPosInc;
940 	nIdx = nIdx + nIdxInc;
941 	pPoints[nPos].X() = (long) (fU2 *       pPoints[nIdx  ].X() +
942 								fT  * fU *  pPoints[nIdx+1].X() * 2 +
943 								fT2 *       pPoints[nIdx+2].X());
944 	pPoints[nPos].Y() = (long) (fU2 *       pPoints[nIdx  ].Y() +
945 								fT  * fU *  pPoints[nIdx+1].Y() * 2 +
946 								fT2 *       pPoints[nIdx+2].Y());
947 	nPos = nPos + nPosInc;
948 	nIdx = nIdx + nIdxInc;
949 	pPoints[nPos].X() = (long) (fU * pPoints[nIdx  ].X() +
950 								fT * pPoints[nIdx+1].X());
951 	pPoints[nPos].Y() = (long) (fU * pPoints[nIdx  ].Y() +
952 								fT * pPoints[nIdx+1].Y());
953 }
954 
955 /************************************************************************/
956 
957 void XPolygon::GenBezArc(const Point& rCenter, long nRx, long nRy,
958 						 long nXHdl, long nYHdl, sal_uInt16 nStart, sal_uInt16 nEnd,
959 						 sal_uInt16 nQuad, sal_uInt16 nFirst)
960 {
961 	Point* pPoints = pImpXPolygon->pPointAry;
962 	pPoints[nFirst  ] = rCenter;
963 	pPoints[nFirst+3] = rCenter;
964 
965 	if ( nQuad == 1 || nQuad == 2 )
966 	{
967 		nRx   = -nRx; nXHdl = -nXHdl;
968 	}
969 	if ( nQuad == 0 || nQuad == 1 )
970 	{
971 		nRy   = -nRy; nYHdl = -nYHdl;
972 	}
973 
974 	if ( nQuad == 0 || nQuad == 2 )
975 	{
976 		pPoints[nFirst].X() += nRx; pPoints[nFirst+3].Y() += nRy;
977 	}
978 	else
979 	{
980 		pPoints[nFirst].Y() += nRy; pPoints[nFirst+3].X() += nRx;
981 	}
982 	pPoints[nFirst+1] = pPoints[nFirst];
983 	pPoints[nFirst+2] = pPoints[nFirst+3];
984 
985 	if ( nQuad == 0 || nQuad == 2 )
986 	{
987 		pPoints[nFirst+1].Y() += nYHdl; pPoints[nFirst+2].X() += nXHdl;
988 	}
989 	else
990 	{
991 		pPoints[nFirst+1].X() += nXHdl; pPoints[nFirst+2].Y() += nYHdl;
992 	}
993 	if ( nStart > 0 )
994 		SubdivideBezier(nFirst, sal_False, (double)nStart / 900);
995 	if ( nEnd < 900 )
996 		SubdivideBezier(nFirst, sal_True, (double)(nEnd-nStart) / (900-nStart));
997 	SetFlags(nFirst+1, XPOLY_CONTROL);
998 	SetFlags(nFirst+2, XPOLY_CONTROL);
999 }
1000 
1001 /************************************************************************/
1002 
1003 sal_Bool XPolygon::CheckAngles(sal_uInt16& nStart, sal_uInt16 nEnd, sal_uInt16& nA1, sal_uInt16& nA2)
1004 {
1005 	if ( nStart == 3600 ) nStart = 0;
1006 	if ( nEnd == 0 ) nEnd = 3600;
1007 	sal_uInt16 nStPrev = nStart;
1008 	sal_uInt16 nMax = (nStart / 900 + 1) * 900;
1009 	sal_uInt16 nMin = nMax - 900;
1010 
1011 	if ( nEnd >= nMax || nEnd <= nStart )   nA2 = 900;
1012 	else                                    nA2 = nEnd - nMin;
1013 	nA1 = nStart - nMin;
1014 	nStart = nMax;
1015 
1016 	// sal_True zurueck, falls letztes Segment berechnet wurde
1017 	return (nStPrev < nEnd && nStart >= nEnd);
1018 }
1019 
1020 /*************************************************************************
1021 |*
1022 |*    XPolygon::CalcSmoothJoin()
1023 |*
1024 |*    glatten Uebergang zu einer Bezierkurve berechnen, indem der
1025 |*    entsprechende Punkt auf die Verbindungslinie von zwei anderen
1026 |*    Punkten projiziert wird
1027 |*     Center = End- bzw. Anfangspunkt der Bezierkurve
1028 |*     Drag   = der bewegte Punkt, der die Verschiebung von Pnt vorgibt
1029 |*     Pnt    = der zu modifizierende Punkt
1030 |*    Wenn Center am Anfang bzw. Ende des Polygons liegt, wird Pnt
1031 |*    auf die entgegengesetzte Seite verlegt
1032 |*    Ersterstellung    ESO 09.01.95
1033 |*    Letzte Aenderung  ESO 18.04.95
1034 |*
1035 \************************************************************************/
1036 
1037 void XPolygon::CalcSmoothJoin(sal_uInt16 nCenter, sal_uInt16 nDrag, sal_uInt16 nPnt)
1038 {
1039 	CheckReference();
1040 
1041 //	sal_uInt16  nMaxPnt = pImpXPolygon->nPoints - 1;
1042 
1043 //  if ( nCenter == nMaxPnt )   nPnt = 1;
1044 //  else if ( nCenter == 0 )    nPnt = nMaxPnt - 1;
1045 
1046 	// Wenn nPnt kein Control-Punkt, d.h. nicht verschiebbar, dann
1047 	// statt dessen nDrag auf der Achse nCenter-nPnt verschieben
1048 	if ( !IsControl(nPnt) )
1049 	{
1050 		sal_uInt16 nTmp = nDrag;
1051 		nDrag = nPnt;
1052 		nPnt = nTmp;
1053 	}
1054 	Point*  pPoints = pImpXPolygon->pPointAry;
1055 	Point   aDiff   = pPoints[nDrag] - pPoints[nCenter];
1056 	double  fDiv    = CalcDistance(nCenter, nDrag);
1057 
1058 	if ( fDiv )
1059 	{
1060 		double fRatio = CalcDistance(nCenter, nPnt) / fDiv;
1061 		// bei SMOOTH bisherige Laenge beibehalten
1062 		if ( GetFlags(nCenter) == XPOLY_SMOOTH || !IsControl(nDrag) )
1063 		{
1064 			aDiff.X() = (long) (fRatio * aDiff.X());
1065 			aDiff.Y() = (long) (fRatio * aDiff.Y());
1066 		}
1067 		pPoints[nPnt] = pPoints[nCenter] - aDiff;
1068 	}
1069 }
1070 
1071 /*************************************************************************
1072 |*
1073 |*    XPolygon::CalcTangent()
1074 |*
1075 |*    Tangente fuer den Uebergang zwischen zwei Bezierkurven berechnen
1076 |*     Center = End- bzw. Anfangspunkt der Bezierkurven
1077 |*     Prev   = vorheriger Zugpunkt
1078 |*     Next   = naechster Zugpunkt
1079 |*    Ersterstellung    ESO 09.01.95
1080 |*    Letzte Aenderung  ESO 18.04.95
1081 |*
1082 \************************************************************************/
1083 
1084 void XPolygon::CalcTangent(sal_uInt16 nCenter, sal_uInt16 nPrev, sal_uInt16 nNext)
1085 {
1086 	CheckReference();
1087 
1088 	double fAbsLen = CalcDistance(nNext, nPrev);
1089 
1090 	if ( fAbsLen )
1091 	{
1092 		const Point& rCenter = pImpXPolygon->pPointAry[nCenter];
1093 		Point&  rNext = pImpXPolygon->pPointAry[nNext];
1094 		Point&  rPrev = pImpXPolygon->pPointAry[nPrev];
1095 		Point   aDiff = rNext - rPrev;
1096 		double  fNextLen = CalcDistance(nCenter, nNext) / fAbsLen;
1097 		double  fPrevLen = CalcDistance(nCenter, nPrev) / fAbsLen;
1098 
1099 		// bei SYMMTR gleiche Laenge fuer beide Seiten
1100 		if ( GetFlags(nCenter) == XPOLY_SYMMTR )
1101 		{
1102 			fPrevLen = (fNextLen + fPrevLen) / 2;
1103 			fNextLen = fPrevLen;
1104 		}
1105 		rNext.X() = rCenter.X() + (long) (fNextLen * aDiff.X());
1106 		rNext.Y() = rCenter.Y() + (long) (fNextLen * aDiff.Y());
1107 		rPrev.X() = rCenter.X() - (long) (fPrevLen * aDiff.X());
1108 		rPrev.Y() = rCenter.Y() - (long) (fPrevLen * aDiff.Y());
1109 	}
1110 }
1111 
1112 /*************************************************************************
1113 |*
1114 |*    XPolygon::PointsToBezier()
1115 |*
1116 |*    wandelt vier Polygonpunkte in eine Bezierkurve durch diese Punkte um
1117 |*    Ersterstellung    ESO 09.01.95
1118 |*    Letzte Aenderung  ESO 09.01.95
1119 |*
1120 \************************************************************************/
1121 
1122 void XPolygon::PointsToBezier(sal_uInt16 nFirst)
1123 {
1124 	double  nFullLength, nPart1Length, nPart2Length;
1125 	double  fX0, fY0, fX1, fY1, fX2, fY2, fX3, fY3;
1126 	double  fTx1, fTx2, fTy1, fTy2;
1127 	double  fT1, fU1, fT2, fU2, fV;
1128 	Point*  pPoints = pImpXPolygon->pPointAry;
1129 
1130 	if ( nFirst > pImpXPolygon->nPoints - 4 || IsControl(nFirst) ||
1131 		 IsControl(nFirst+1) || IsControl(nFirst+2) || IsControl(nFirst+3) )
1132 		return;
1133 
1134 	CheckReference();
1135 
1136 	fTx1 = pPoints[nFirst+1].X();
1137 	fTy1 = pPoints[nFirst+1].Y();
1138 	fTx2 = pPoints[nFirst+2].X();
1139 	fTy2 = pPoints[nFirst+2].Y();
1140 	fX0  = pPoints[nFirst  ].X();
1141 	fY0  = pPoints[nFirst  ].Y();
1142 	fX3  = pPoints[nFirst+3].X();
1143 	fY3  = pPoints[nFirst+3].Y();
1144 
1145 	nPart1Length = CalcDistance(nFirst, nFirst+1);
1146 	nPart2Length = nPart1Length + CalcDistance(nFirst+1, nFirst+2);
1147 	nFullLength  = nPart2Length + CalcDistance(nFirst+2, nFirst+3);
1148 	if ( nFullLength < 20 )
1149 		return;
1150 
1151 	if ( nPart2Length == nFullLength )
1152 		nPart2Length -= 1;
1153 	if ( nPart1Length == nFullLength )
1154 		nPart1Length = nPart2Length - 1;
1155 	if ( nPart1Length <= 0 )
1156 		nPart1Length = 1;
1157 	if ( nPart2Length <= 0 || nPart2Length == nPart1Length )
1158 		nPart2Length = nPart1Length + 1;
1159 
1160 	fT1 = nPart1Length / nFullLength;
1161 	fU1 = 1.0 - fT1;
1162 	fT2 = nPart2Length / nFullLength;
1163 	fU2 = 1.0 - fT2;
1164 	fV = 3 * (1.0 - (fT1 * fU2) / (fT2 * fU1));
1165 
1166 	fX1 = fTx1 / (fT1 * fU1 * fU1) - fTx2 * fT1 / (fT2 * fT2 * fU1 * fU2);
1167 	fX1 /= fV;
1168 	fX1 -= fX0 * ( fU1 / fT1 + fU2 / fT2) / 3;
1169 	fX1 += fX3 * ( fT1 * fT2 / (fU1 * fU2)) / 3;
1170 
1171 	fY1 = fTy1 / (fT1 * fU1 * fU1) - fTy2 * fT1 / (fT2 * fT2 * fU1 * fU2);
1172 	fY1 /= fV;
1173 	fY1 -= fY0 * ( fU1 / fT1 + fU2 / fT2) / 3;
1174 	fY1 += fY3 * ( fT1 * fT2 / (fU1 * fU2)) / 3;
1175 
1176 	fX2 = fTx2 / (fT2 * fT2 * fU2 * 3) - fX0 * fU2 * fU2 / ( fT2 * fT2 * 3);
1177 	fX2 -= fX1 * fU2 / fT2;
1178 	fX2 -= fX3 * fT2 / (fU2 * 3);
1179 
1180 	fY2 = fTy2 / (fT2 * fT2 * fU2 * 3) - fY0 * fU2 * fU2 / ( fT2 * fT2 * 3);
1181 	fY2 -= fY1 * fU2 / fT2;
1182 	fY2 -= fY3 * fT2 / (fU2 * 3);
1183 
1184 	pPoints[nFirst+1] = Point((long) fX1, (long) fY1);
1185 	pPoints[nFirst+2] = Point((long) fX2, (long) fY2);
1186 	SetFlags(nFirst+1, XPOLY_CONTROL);
1187 	SetFlags(nFirst+2, XPOLY_CONTROL);
1188 }
1189 
1190 /*************************************************************************
1191 |*
1192 |*    XPolygon::Translate()
1193 |*
1194 |*    Polygon auf den uebergebenen Punkt verschieben
1195 |*    Ersterstellung    ESO 17.01.95
1196 |*    Letzte Aenderung  ESO 17.01.95
1197 |*
1198 *************************************************************************/
1199 
1200 void XPolygon::Translate(const Point& rTrans)
1201 {
1202 	pImpXPolygon->CheckPointDelete();
1203 	CheckReference();
1204 
1205 	sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
1206 
1207 	for (sal_uInt16 i = 0; i < nPntCnt; i++)
1208 		pImpXPolygon->pPointAry[i] += rTrans;
1209 }
1210 
1211 /*************************************************************************
1212 |*
1213 |*    XPolygon::Rotate()
1214 |*
1215 |*    Alle Punkte um den Punkt rCenter drehen, Sinus und Cosinus
1216 |*    muessen uebergeben werden
1217 |*    Ersterstellung    ESO 09.01.95
1218 |*    Letzte Aenderung  ESO 17.01.95
1219 |*
1220 *************************************************************************/
1221 
1222 void XPolygon::Rotate(const Point& rCenter, double fSin, double fCos)
1223 {
1224 	pImpXPolygon->CheckPointDelete();
1225 	CheckReference();
1226 
1227 	long nX;
1228 	long nY;
1229 	long nNewX;
1230 	long nNewY;
1231 	long nCenterX = rCenter.X();
1232 	long nCenterY = rCenter.Y();
1233 
1234 	sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
1235 
1236 	for (sal_uInt16 i = 0; i < nPntCnt; i++)
1237 	{
1238 		Point *pPt = &(pImpXPolygon->pPointAry[i]);
1239 		nX = pPt->X()-nCenterX;
1240 		nY = pPt->Y()-nCenterY;
1241 		nNewX =  (long)floor(fCos * nX + fSin * nY + 0.5);
1242 		nNewY = -(long)floor(fSin * nX - fCos * nY + 0.5);
1243 		pPt->X() = nNewX + nCenterX;
1244 		pPt->Y() = nNewY + nCenterY;
1245 
1246 	/* und so stand das in einem anderen File auf T:
1247 	   dass ich am 29-11-1995 gegettet habe. Joe M.
1248 	sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
1249 
1250 	for (sal_uInt16 i = 0; i < nPntCnt; i++)
1251 	{
1252 		Point P = pImpXPolygon->pPointAry[i] - rCenter;
1253 		long X = P.X();
1254 		long Y = P.Y();
1255 		P.X() =  (long)floor(fCos * X + fSin * Y + 0.5);
1256 		P.Y() = -(long)floor(fSin * X - fCos * Y + 0.5);
1257 		pImpXPolygon->pPointAry[i] = P + rCenter;
1258 	*/
1259 	}
1260 }
1261 
1262 /*************************************************************************
1263 |*
1264 |*    XPolygon::Rotate()
1265 |*
1266 |*    Alle Punkte um den Punkt rCenter mit dem Winkel nAngle drehen
1267 |*    Winkel in 10tel Grad, Wertebereich 0 - 3600
1268 |*    Ersterstellung    ESO 17.01.95
1269 |*    Letzte Aenderung  ESO 17.01.95
1270 |*
1271 *************************************************************************/
1272 
1273 void XPolygon::Rotate(const Point& rCenter, sal_uInt16 nAngle)
1274 {
1275 	nAngle %= 3600;
1276 
1277 	if ( nAngle != 0 )
1278 	{
1279 		double fAngle = F_PI * nAngle / 1800;
1280 		double fSin = sin(fAngle);
1281 		double fCos = cos(fAngle);
1282 		Rotate(rCenter, fSin, fCos);
1283 	}
1284 }
1285 
1286 /*************************************************************************
1287 |*
1288 |*    XPolygon::Scale()
1289 |*
1290 |*    XPolygon in X- und/oder Y-Richtung skalieren
1291 |*    Ersterstellung    ESO 01.02.95
1292 |*    Letzte Aenderung  ESO 01.02.95
1293 |*
1294 *************************************************************************/
1295 
1296 void XPolygon::Scale(double fSx, double fSy)
1297 {
1298 	pImpXPolygon->CheckPointDelete();
1299 	CheckReference();
1300 
1301 	sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
1302 
1303 	for (sal_uInt16 i = 0; i < nPntCnt; i++)
1304 	{
1305 		Point& rPnt = pImpXPolygon->pPointAry[i];
1306 		rPnt.X() = (long)(fSx * rPnt.X());
1307 		rPnt.Y() = (long)(fSy * rPnt.Y());
1308 	}
1309 }
1310 
1311 /*************************************************************************
1312 |*
1313 |*    XPolygon::SlantX()
1314 |*
1315 |*    XPolygon in X-Richtung um einen beliebigen Winkel kippen,
1316 |*    bezogen auf eine Referenz-Y-Koordinate
1317 |*    Ersterstellung    ESO 01.02.95
1318 |*    Letzte Aenderung  ESO 01.02.95
1319 |*
1320 *************************************************************************/
1321 
1322 void XPolygon::SlantX(long nYRef, double fSin, double fCos)
1323 {
1324 	pImpXPolygon->CheckPointDelete();
1325 	CheckReference();
1326 
1327 	sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
1328 
1329 	for (sal_uInt16 i = 0; i < nPntCnt; i++)
1330 	{
1331 		Point& rPnt = pImpXPolygon->pPointAry[i];
1332 		long nDy = rPnt.Y() - nYRef;
1333 		rPnt.X() += (long)(fSin * nDy);
1334 		rPnt.Y() = nYRef + (long)(fCos * nDy);
1335 	}
1336 }
1337 
1338 /*************************************************************************
1339 |*
1340 |*    XPolygon::SlantY()
1341 |*
1342 |*    XPolygon in Y-Richtung um einen beliebigen Winkel kippen,
1343 |*    bezogen auf eine Referenz-X-Koordinate
1344 |*    Ersterstellung    ESO 01.02.95
1345 |*    Letzte Aenderung  ESO 01.02.95
1346 |*
1347 *************************************************************************/
1348 
1349 void XPolygon::SlantY(long nXRef, double fSin, double fCos)
1350 {
1351 	pImpXPolygon->CheckPointDelete();
1352 	CheckReference();
1353 
1354 	sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
1355 
1356 	for (sal_uInt16 i = 0; i < nPntCnt; i++)
1357 	{
1358 		Point& rPnt = pImpXPolygon->pPointAry[i];
1359 		long nDx = rPnt.X() - nXRef;
1360 		rPnt.X() = nXRef + (long)(fCos * nDx);
1361 		rPnt.Y() -= (long)(fSin * nDx);
1362 	}
1363 }
1364 
1365 /*************************************************************************
1366 |*
1367 |*    XPolygon::Distort()
1368 |*
1369 |*    XPolygon verzerren, indem die Koordinaten relativ zu einem
1370 |*    Referenzrechteck in ein beliebiges Viereck skaliert werden
1371 |*    Zuordnung der Viereck-Punkte im Polygon zum Referenzrechteck:
1372 |*    0: links oben      0----1
1373 |*    1: rechts oben     |    |
1374 |*    2: rechts unten    3----2
1375 |*    3: links unten
1376 |*    Ersterstellung    ESO 07.07.95
1377 |*    Letzte Aenderung  ESO 07.07.95
1378 |*
1379 *************************************************************************/
1380 
1381 void XPolygon::Distort(const Rectangle& rRefRect,
1382 					   const XPolygon& rDistortedRect)
1383 {
1384 	pImpXPolygon->CheckPointDelete();
1385 	CheckReference();
1386 
1387 	long    Xr, Wr, X1, X2, X3, X4;
1388 	long    Yr, Hr, Y1, Y2, Y3, Y4;
1389 	double  fTx, fTy, fUx, fUy;
1390 
1391 	Xr = rRefRect.Left();
1392 	Yr = rRefRect.Top();
1393 	Wr = rRefRect.GetWidth();
1394 	Hr = rRefRect.GetHeight();
1395 
1396 	if ( Wr && Hr )
1397 	{
1398 		DBG_ASSERT(rDistortedRect.pImpXPolygon->nPoints >= 4,
1399 				   "Distort-Rechteck zu klein");
1400 
1401 		X1 = rDistortedRect[0].X();
1402 		Y1 = rDistortedRect[0].Y();
1403 		X2 = rDistortedRect[1].X();
1404 		Y2 = rDistortedRect[1].Y();
1405 		X3 = rDistortedRect[3].X();
1406 		Y3 = rDistortedRect[3].Y();
1407 		X4 = rDistortedRect[2].X();
1408 		Y4 = rDistortedRect[2].Y();
1409 
1410 		sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
1411 
1412 		for (sal_uInt16 i = 0; i < nPntCnt; i++)
1413 		{
1414 			Point& rPnt = pImpXPolygon->pPointAry[i];
1415 
1416 			fTx = (double)(rPnt.X() - Xr) / Wr;
1417 			fTy = (double)(rPnt.Y() - Yr) / Hr;
1418 			fUx = 1.0 - fTx;
1419 			fUy = 1.0 - fTy;
1420 
1421 			rPnt.X() = (long) ( fUy * (fUx * X1 + fTx * X2) +
1422 								fTy * (fUx * X3 + fTx * X4) );
1423 			rPnt.Y() = (long) ( fUx * (fUy * Y1 + fTy * Y3) +
1424 								fTx * (fUy * Y2 + fTy * Y4) );
1425 		}
1426 	}
1427 }
1428 
1429 /*************************************************************************
1430 |*
1431 |* Bestimme den linken, unteren Punkt des Polygons und richte das
1432 |* Polygon so aus, dass dieser Punkt auf dem Index 0 liegt
1433 |*
1434 \************************************************************************/
1435 
1436 void XPolygon::Rotate20()
1437 {
1438 	pImpXPolygon->CheckPointDelete();
1439 	CheckReference();
1440 
1441 	double   fMinY   = pImpXPolygon->pPointAry->Y();
1442 	double   fMinX   = pImpXPolygon->pPointAry->X();
1443 	long     nPntCnt = pImpXPolygon->nPoints;
1444 	long     nIndex0 = 0;
1445 
1446 	for (long nPoints = 1;
1447 			  nPoints < nPntCnt;
1448 			  nPoints ++)
1449 	{
1450 		Point &rPnt = pImpXPolygon->pPointAry[nPoints];
1451 
1452 		if ((rPnt.X () < fMinX) || (fMinX == rPnt.X ()) &&
1453 								   (fMinY >= rPnt.Y ()))
1454 		{
1455 			fMinX   = rPnt.X ();
1456 			fMinY   = rPnt.Y ();
1457 			nIndex0 = nPoints;
1458 		}
1459 	}
1460 
1461 	if (nIndex0 < nPntCnt)
1462 	{
1463 		Point *pTemp = new Point [nIndex0];
1464 		memcpy (pTemp, pImpXPolygon->pPointAry, nIndex0 * sizeof (Point));
1465 		memcpy (pImpXPolygon->pPointAry, &pImpXPolygon->pPointAry [nIndex0], (nPntCnt - nIndex0) * sizeof (Point));
1466 		memcpy (&pImpXPolygon->pPointAry [nIndex0], pTemp, nIndex0 * sizeof (Point));
1467 		delete[] pTemp;
1468 	}
1469 }
1470 
1471 basegfx::B2DPolygon XPolygon::getB2DPolygon() const
1472 {
1473 	// #i74631# use tools Polygon class for conversion to not have the code doubled
1474 	// here. This needs one more conversion but avoids different convertors in
1475 	// the long run
1476 	DBG_ASSERT(pImpXPolygon != 0, "XPolygon::getB2DPolygon(): XPolygon has no implementation incarnated (!)");
1477 	const Polygon aSource(GetPointCount(), pImpXPolygon->pPointAry, pImpXPolygon->pFlagAry);
1478 
1479 	return aSource.getB2DPolygon();
1480 }
1481 
1482 XPolygon::XPolygon(const basegfx::B2DPolygon& rPolygon)
1483 {
1484 	// #i74631# use tools Polygon class for conversion to not have the code doubled
1485 	// here. This needs one more conversion but avoids different convertors in
1486 	// the long run
1487 	DBG_CTOR(XPolygon,NULL);
1488 
1489 	const Polygon aSource(rPolygon);
1490 	sal_uInt16 nSize = aSource.GetSize();
1491 	pImpXPolygon = new ImpXPolygon( nSize );
1492 	pImpXPolygon->nPoints = nSize;
1493 
1494 	for( sal_uInt16 i = 0; i < nSize;  i++ )
1495 	{
1496 		pImpXPolygon->pPointAry[i] = aSource[i];
1497 		pImpXPolygon->pFlagAry[i] = (sal_uInt8) aSource.GetFlags( i );
1498 	}
1499 }
1500 
1501 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1502 //+--------------- XPolyPolygon -----------------------------------------+
1503 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1504 
1505 /*************************************************************************
1506 |*
1507 |*    ImpXPolyPolygon::ImpXPolyPolygon()
1508 |*
1509 |*    Beschreibung      Erzeugt das XPolygon-Array
1510 |*    Ersterstellung    CL 09.11.94
1511 |*    Letzte Aenderung  MM 09.11.94
1512 |*
1513 *************************************************************************/
1514 
1515 ImpXPolyPolygon::ImpXPolyPolygon( const ImpXPolyPolygon& rImpXPolyPoly ) :
1516 					 aXPolyList( rImpXPolyPoly.aXPolyList )
1517 {
1518 	nRefCount = 1;
1519 
1520 	// Einzelne Elemente duplizieren
1521 	XPolygon* pXPoly = aXPolyList.First();
1522 	while ( pXPoly )
1523 	{
1524 		aXPolyList.Replace( new XPolygon( *(aXPolyList.GetCurObject()) ) );
1525 		pXPoly = aXPolyList.Next();
1526 	}
1527 }
1528 
1529 
1530 /*************************************************************************
1531 |*
1532 |*    ImpXPolyPolygon::~ImpXPolyPolygon()
1533 |*
1534 |*    Beschreibung      Loescht das Polygon-Array
1535 |*    Ersterstellung    CL 09.06.93
1536 |*    Letzte Aenderung  CL 09.06.93
1537 |*
1538 *************************************************************************/
1539 
1540 ImpXPolyPolygon::~ImpXPolyPolygon()
1541 {
1542 	XPolygon* pXPoly = aXPolyList.First();
1543 	while( pXPoly )
1544 	{
1545 		delete pXPoly;
1546 		pXPoly = aXPolyList.Next();
1547 	}
1548 }
1549 
1550 /*************************************************************************
1551 |*
1552 |*    ImpXPolyPolygon::operator==()
1553 |*
1554 |*    Ersterstellung    Joe 26-09-95
1555 |*    Letzte Aenderung
1556 |*
1557 *************************************************************************/
1558 
1559 
1560 bool ImpXPolyPolygon::operator==(const ImpXPolyPolygon& rImpXPolyPoly) const
1561 {
1562 	sal_uInt16 nAnz=(sal_uInt16)aXPolyList.Count();
1563 	const XPolygonList& rCmpList=rImpXPolyPoly.aXPolyList;
1564 	if (nAnz!=(sal_uInt16)rCmpList.Count()) return sal_False;
1565 	bool bEq=true;
1566 	for (sal_uInt16 i=nAnz; i>0 && bEq;) {
1567 		i--;
1568 		bEq= *aXPolyList.GetObject(i) == *rCmpList.GetObject(i);
1569 	}
1570 	return bEq;
1571 }
1572 
1573 /*************************************************************************
1574 |*
1575 |*    XPolyPolygon::XPolyPolygon()
1576 |*
1577 |*    Beschreibung      POLY.SDW
1578 |*    Ersterstellung    CL 27.01.93
1579 |*    Letzte Aenderung  CL 27.01.93
1580 |*
1581 *************************************************************************/
1582 
1583 XPolyPolygon::XPolyPolygon( sal_uInt16 nInitSize, sal_uInt16 nResize )
1584 {
1585 	DBG_CTOR(XPolyPolygon,NULL);
1586 	pImpXPolyPolygon = new ImpXPolyPolygon( nInitSize, nResize );
1587 }
1588 
1589 
1590 /*************************************************************************
1591 |*
1592 |*    XPolyPolygon::XPolyPolygon()
1593 |*
1594 |*    Beschreibung      POLY.SDW
1595 |*    Ersterstellung    CL 27.01.93
1596 |*    Letzte Aenderung  CL 27.01.93
1597 |*
1598 *************************************************************************/
1599 
1600 XPolyPolygon::XPolyPolygon( const XPolygon& rXPoly )
1601 {
1602 	DBG_CTOR(XPolyPolygon,NULL);
1603 	pImpXPolyPolygon = new ImpXPolyPolygon;
1604 	pImpXPolyPolygon->aXPolyList.Insert( new XPolygon( rXPoly ) );
1605 }
1606 
1607 /*************************************************************************
1608 |*
1609 |*    XPolyPolygon::XPolyPolygon()
1610 |*
1611 |*    Beschreibung      POLY.SDW
1612 |*    Ersterstellung    CL 27.01.93
1613 |*    Letzte Aenderung  CL 27.01.93
1614 |*
1615 *************************************************************************/
1616 
1617 XPolyPolygon::XPolyPolygon( const XPolyPolygon& rXPolyPoly )
1618 {
1619 	DBG_CTOR(XPolyPolygon,NULL);
1620 	pImpXPolyPolygon = rXPolyPoly.pImpXPolyPolygon;
1621 	pImpXPolyPolygon->nRefCount++;
1622 }
1623 
1624 /*************************************************************************
1625 |*
1626 |*    XPolyPolygon::XPolyPolygon()
1627 |*
1628 |*    XPolyPolygon aus einen Standard-PolyPolygon erzeugen
1629 |*    Ersterstellung    18.01.95 ESO
1630 |*    Letzte Aenderung  18.01.95 ESO
1631 |*
1632 *************************************************************************/
1633 
1634 XPolyPolygon::XPolyPolygon( const PolyPolygon& rPolyPoly )
1635 {
1636 	DBG_CTOR(XPolyPolygon,NULL);
1637 	pImpXPolyPolygon = new ImpXPolyPolygon;
1638 
1639 	for (sal_uInt16 i = 0; i < rPolyPoly.Count(); i++)
1640 		pImpXPolyPolygon->aXPolyList.Insert(
1641 									new XPolygon(rPolyPoly.GetObject(i)) );
1642 }
1643 
1644 /*************************************************************************
1645 |*
1646 |*    XPolyPolygon::~XPolyPolygon()
1647 |*
1648 |*    Beschreibung      POLY.SDW
1649 |*    Ersterstellung    CL 27.01.93
1650 |*    Letzte Aenderung  CL 27.01.93
1651 |*
1652 *************************************************************************/
1653 
1654 XPolyPolygon::~XPolyPolygon()
1655 {
1656 	DBG_DTOR(XPolyPolygon,NULL);
1657 	if( pImpXPolyPolygon->nRefCount > 1 )
1658 		pImpXPolyPolygon->nRefCount--;
1659 	else
1660 		delete pImpXPolyPolygon;
1661 }
1662 
1663 /*************************************************************************
1664 |*
1665 |*    XPolygon::CheckReference()
1666 |*
1667 |*    Referenzzaehler desImpXPolyPoly pruefen und ggf. von diesem abkoppeln
1668 |*    Ersterstellung    18.01.95 ESO
1669 |*    Letzte Aenderung  18.01.95 ESO
1670 |*
1671 *************************************************************************/
1672 
1673 void XPolyPolygon::CheckReference()
1674 {
1675 	if( pImpXPolyPolygon->nRefCount > 1 )
1676 	{
1677 		pImpXPolyPolygon->nRefCount--;
1678 		pImpXPolyPolygon = new ImpXPolyPolygon( *pImpXPolyPolygon );
1679 	}
1680 }
1681 
1682 /*************************************************************************
1683 |*
1684 |*    XPolyPolygon::Insert()
1685 |*
1686 |*    Beschreibung      POLY.SDW
1687 |*    Ersterstellung    CL 27.01.93
1688 |*    Letzte Aenderung  CL 27.01.93
1689 |*
1690 *************************************************************************/
1691 
1692 void XPolyPolygon::Insert( const XPolygon& rXPoly, sal_uInt16 nPos )
1693 {
1694 	CheckReference();
1695 	XPolygon* pXPoly = new XPolygon( rXPoly );
1696 	pImpXPolyPolygon->aXPolyList.Insert( pXPoly, nPos );
1697 }
1698 
1699 /*************************************************************************
1700 |*
1701 |*    XPolyPolygon::Insert()
1702 |*
1703 |*    saemtliche XPolygone aus einem XPolyPolygon einfuegen
1704 |*    Ersterstellung    18.01.95 ESO
1705 |*    Letzte Aenderung  18.01.95 ESO
1706 |*
1707 *************************************************************************/
1708 
1709 void XPolyPolygon::Insert( const XPolyPolygon& rXPolyPoly, sal_uInt16 nPos )
1710 {
1711 	CheckReference();
1712 
1713 	for (sal_uInt16 i = 0; i < rXPolyPoly.Count(); i++)
1714 	{
1715 		XPolygon* pXPoly = new XPolygon(rXPolyPoly[i]);
1716 		pImpXPolyPolygon->aXPolyList.Insert(pXPoly, nPos);
1717 		if ( nPos != XPOLYPOLY_APPEND )
1718 			nPos++;
1719 	}
1720 }
1721 
1722 /*************************************************************************
1723 |*
1724 |*    XPolyPolygon::Remove()
1725 |*
1726 |*    Beschreibung      POLY.SDW
1727 |*    Ersterstellung    CL 27.01.93
1728 |*    Letzte Aenderung  CL 27.01.93
1729 |*
1730 *************************************************************************/
1731 
1732 XPolygon XPolyPolygon::Remove( sal_uInt16 nPos )
1733 {
1734 	CheckReference();
1735 	XPolygon* pTmpXPoly = pImpXPolyPolygon->aXPolyList.Remove( nPos );
1736 	XPolygon  aXPoly( *pTmpXPoly );
1737 	delete pTmpXPoly;
1738 	return aXPoly;
1739 }
1740 
1741 
1742 /*************************************************************************
1743 |*
1744 |*    XPolyPolygon::Replace()
1745 |*
1746 |*    Beschreibung      POLY.SDW
1747 |*    Ersterstellung    CL 27.01.93
1748 |*    Letzte Aenderung  CL 27.01.93
1749 |*
1750 *************************************************************************/
1751 
1752 XPolygon XPolyPolygon::Replace( const XPolygon& rXPoly, sal_uInt16 nPos )
1753 {
1754 	CheckReference();
1755 	XPolygon* pXPoly = new XPolygon( rXPoly );
1756 	XPolygon* pTmpXPoly = pImpXPolyPolygon->aXPolyList.Replace( pXPoly, nPos );
1757 	XPolygon  aXPoly( *pTmpXPoly );
1758 	delete pTmpXPoly;
1759 	return aXPoly;
1760 }
1761 
1762 
1763 /*************************************************************************
1764 |*
1765 |*    XPolyPolygon::GetObject()
1766 |*
1767 |*    Beschreibung      POLY.SDW
1768 |*    Ersterstellung    CL 27.01.93
1769 |*    Letzte Aenderung  CL 27.01.93
1770 |*
1771 *************************************************************************/
1772 
1773 const XPolygon& XPolyPolygon::GetObject( sal_uInt16 nPos ) const
1774 {
1775 	return *(pImpXPolyPolygon->aXPolyList.GetObject( nPos ));
1776 }
1777 
1778 
1779 /*************************************************************************
1780 |*
1781 |*    XPolyPolygon::Clear()
1782 |*
1783 |*    Beschreibung      POLY.SDW
1784 |*    Ersterstellung    CL 27.01.93
1785 |*    Letzte Aenderung  TH 17.10.94
1786 |*
1787 *************************************************************************/
1788 
1789 void XPolyPolygon::Clear()
1790 {
1791 	if ( pImpXPolyPolygon->nRefCount > 1 )
1792 	{
1793 		pImpXPolyPolygon->nRefCount--;
1794 		pImpXPolyPolygon = new ImpXPolyPolygon();
1795 	}
1796 	else
1797 	{
1798 		XPolygon* pXPoly = pImpXPolyPolygon->aXPolyList.First();
1799 		while( pXPoly )
1800 		{
1801 			delete pXPoly;
1802 			pXPoly = pImpXPolyPolygon->aXPolyList.Next();
1803 		}
1804 		pImpXPolyPolygon->aXPolyList.Clear();
1805 	}
1806 }
1807 
1808 
1809 /*************************************************************************
1810 |*
1811 |*    XPolyPolygon::Count()
1812 |*
1813 |*    Beschreibung
1814 |*    Ersterstellung    CL 27.01.93
1815 |*    Letzte Aenderung  CL 27.01.93
1816 |*
1817 *************************************************************************/
1818 
1819 sal_uInt16 XPolyPolygon::Count() const
1820 {
1821 	return (sal_uInt16)(pImpXPolyPolygon->aXPolyList.Count());
1822 }
1823 
1824 
1825 /*************************************************************************
1826 |*
1827 |*    XPolyPolygon::Move()
1828 |*
1829 |*    Beschreibung      POLY.SDW
1830 |*    Ersterstellung    TH 04.10.94
1831 |*    Letzte Aenderung  TH 04.10.94
1832 |*
1833 *************************************************************************/
1834 
1835 void XPolyPolygon::Move( long nHorzMove, long nVertMove )
1836 {
1837 	// Diese Abfrage sollte man fuer die DrawEngine durchfuehren
1838 	if ( !nHorzMove && !nVertMove )
1839 		return;
1840 
1841 	// Referenzcounter beruecksichtigen
1842 	CheckReference();
1843 
1844 	// Punkte verschieben
1845 	XPolygon* pXPoly = pImpXPolyPolygon->aXPolyList.First();
1846 	while( pXPoly )
1847 	{
1848 		pXPoly->Move( nHorzMove, nVertMove );
1849 		pXPoly = pImpXPolyPolygon->aXPolyList.Next();
1850 	}
1851 }
1852 
1853 /*************************************************************************
1854 |*
1855 |*    XPolyPolygon::GetBoundRect()
1856 |*
1857 |*    Beschreibung      POLY.SDW
1858 |*    Ersterstellung    TH 04.10.94
1859 |*    Letzte Aenderung  TH 04.10.94
1860 |*
1861 *************************************************************************/
1862 
1863 Rectangle XPolyPolygon::GetBoundRect() const
1864 {
1865 	sal_uInt16    nXPoly = (sal_uInt16)pImpXPolyPolygon->aXPolyList.Count();
1866 	Rectangle aRect;
1867 
1868 	for ( sal_uInt16 n = 0; n < nXPoly; n++ )
1869 	{
1870 		const XPolygon* pXPoly = pImpXPolyPolygon->aXPolyList.GetObject( n );
1871 		aRect.Union( pXPoly->GetBoundRect() );
1872 	}
1873 
1874 	return aRect;
1875 }
1876 
1877 
1878 /*************************************************************************
1879 |*
1880 |*    XPolyPolygon::operator[]()
1881 |*
1882 |*    Beschreibung      POLY.SDW
1883 |*    Ersterstellung    TH 28.10.94
1884 |*    Letzte Aenderung  TH 28.10.94
1885 |*
1886 *************************************************************************/
1887 
1888 XPolygon& XPolyPolygon::operator[]( sal_uInt16 nPos )
1889 {
1890 	CheckReference();
1891 	return *(pImpXPolyPolygon->aXPolyList.GetObject( nPos ));
1892 }
1893 
1894 /*************************************************************************
1895 |*
1896 |*    XPolyPolygon::operator=()
1897 |*
1898 |*    Beschreibung      POLY.SDW
1899 |*    Ersterstellung    CL 27.01.93
1900 |*    Letzte Aenderung  CL 27.01.93
1901 |*
1902 *************************************************************************/
1903 
1904 XPolyPolygon& XPolyPolygon::operator=( const XPolyPolygon& rXPolyPoly )
1905 {
1906 	rXPolyPoly.pImpXPolyPolygon->nRefCount++;
1907 
1908 	if( pImpXPolyPolygon->nRefCount > 1 )
1909 		pImpXPolyPolygon->nRefCount--;
1910 	else
1911 		delete pImpXPolyPolygon;
1912 
1913 	pImpXPolyPolygon = rXPolyPoly.pImpXPolyPolygon;
1914 	return *this;
1915 }
1916 
1917 
1918 /*************************************************************************
1919 |*
1920 |*    XPolyPolygon::operator==()
1921 |*
1922 |*    Beschreibung      POLY.SDW
1923 |*    Ersterstellung    CL  27.01.93
1924 |*    Letzte Aenderung  Joe 27.01.93
1925 |*
1926 *************************************************************************/
1927 
1928 sal_Bool XPolyPolygon::operator==( const XPolyPolygon& rXPolyPoly ) const
1929 {
1930 	if (pImpXPolyPolygon==rXPolyPoly.pImpXPolyPolygon) return sal_True;
1931 	return *pImpXPolyPolygon == *rXPolyPoly.pImpXPolyPolygon;
1932 }
1933 
1934 
1935 /*************************************************************************
1936 |*
1937 |*    XPolyPolygon::operator!=()
1938 |*
1939 |*    Beschreibung      POLY.SDW
1940 |*    Ersterstellung    CL  27.01.93
1941 |*    Letzte Aenderung  Joe 27.01.93
1942 |*
1943 *************************************************************************/
1944 
1945 sal_Bool XPolyPolygon::operator!=( const XPolyPolygon& rXPolyPoly ) const
1946 {
1947 	if (pImpXPolyPolygon==rXPolyPoly.pImpXPolyPolygon) return sal_False;
1948 	return *pImpXPolyPolygon != *rXPolyPoly.pImpXPolyPolygon;
1949 }
1950 
1951 /*************************************************************************
1952 |*
1953 |*    XPolyPolygon::Translate()
1954 |*
1955 |*    Alle Polygone auf den uebergebenen Punkt verschieben
1956 |*    Ersterstellung    ESO 25.01.95
1957 |*    Letzte Aenderung  ESO 25.01.95
1958 |*
1959 *************************************************************************/
1960 
1961 void XPolyPolygon::Translate(const Point& rTrans)
1962 {
1963 	CheckReference();
1964 
1965 	for (sal_uInt16 i = 0; i < Count(); i++)
1966 		pImpXPolyPolygon->aXPolyList.GetObject(i)->Translate(rTrans);
1967 }
1968 
1969 /*************************************************************************
1970 |*
1971 |*    XPolyPolygon::Rotate()
1972 |*
1973 |*    Alle Polygone um den Punkt rCenter drehen, Sinus und Cosinus
1974 |*    muessen uebergeben werden
1975 |*    Ersterstellung    ESO 25.01.95
1976 |*    Letzte Aenderung  ESO 25.01.95
1977 |*
1978 *************************************************************************/
1979 
1980 void XPolyPolygon::Rotate(const Point& rCenter, double fSin, double fCos)
1981 {
1982 	CheckReference();
1983 
1984 	for (sal_uInt16 i = 0; i < Count(); i++)
1985 		pImpXPolyPolygon->aXPolyList.GetObject(i)->Rotate(rCenter, fSin, fCos);
1986 }
1987 
1988 /*************************************************************************
1989 |*
1990 |* Bestimme den linken, unteren Punkt des Polygons und richte das
1991 |* Polygon so aus, dass dieser Punkt auf dem Index 0 liegt
1992 |*
1993 \************************************************************************/
1994 
1995 void XPolyPolygon::Rotate20()
1996 {
1997 	CheckReference();
1998 
1999 	for (sal_uInt16 i = 0; i < Count(); i++)
2000 		pImpXPolyPolygon->aXPolyList.GetObject(i)->Rotate20();
2001 }
2002 
2003 /*************************************************************************
2004 |*
2005 |*    XPolyPolygon::Rotate()
2006 |*
2007 |*    Alle Poylgone um den Punkt rCenter mit dem Winkel nAngle drehen
2008 |*    Winkel in 10tel Grad, Wertebereich 0 - 3600
2009 |*    Ersterstellung    ESO 25.01.95
2010 |*    Letzte Aenderung  ESO 25.01.95
2011 |*
2012 *************************************************************************/
2013 
2014 void XPolyPolygon::Rotate(const Point& rCenter, sal_uInt16 nAngle)
2015 {
2016 	nAngle %= 3600;
2017 
2018 	if ( nAngle != 0 )
2019 	{
2020 		double fAngle = F_PI * nAngle / 1800;
2021 		double fSin = sin(fAngle);
2022 		double fCos = cos(fAngle);
2023 		Rotate(rCenter, fSin, fCos);
2024 	}
2025 }
2026 
2027 /*************************************************************************
2028 |*
2029 |*    XPolyPolygon::Scale()
2030 |*
2031 |*    Alle Polygone in X- und/oder Y-Richtung skalieren
2032 |*    Ersterstellung    ESO 01.02.95
2033 |*    Letzte Aenderung  ESO 01.02.95
2034 |*
2035 *************************************************************************/
2036 
2037 void XPolyPolygon::Scale(double fSx, double fSy)
2038 {
2039 	CheckReference();
2040 
2041 	for (sal_uInt16 i = 0; i < Count(); i++)
2042 		pImpXPolyPolygon->aXPolyList.GetObject(i)->Scale(fSx, fSy);
2043 }
2044 
2045 /*************************************************************************
2046 |*
2047 |*    XPolyPolygon::SlantX()
2048 |*
2049 |*    Alle Polygone in X-Richtung um einen beliebigen Winkel kippen,
2050 |*    bezogen auf eine Referenz-Y-Koordinate
2051 |*    Ersterstellung    ESO 01.02.95
2052 |*    Letzte Aenderung  ESO 01.02.95
2053 |*
2054 *************************************************************************/
2055 
2056 void XPolyPolygon::SlantX(long nYRef, double fSin, double fCos)
2057 {
2058 	CheckReference();
2059 
2060 	for (sal_uInt16 i = 0; i < Count(); i++)
2061 		pImpXPolyPolygon->aXPolyList.GetObject(i)->SlantX(nYRef, fSin, fCos);
2062 }
2063 
2064 /*************************************************************************
2065 |*
2066 |*    XPolyPolygon::SlantY()
2067 |*
2068 |*    Alle Polygone in Y-Richtung um einen beliebigen Winkel kippen,
2069 |*    bezogen auf eine Referenz-X-Koordinate
2070 |*    Ersterstellung    ESO 01.02.95
2071 |*    Letzte Aenderung  ESO 01.02.95
2072 |*
2073 *************************************************************************/
2074 
2075 void XPolyPolygon::SlantY(long nXRef, double fSin, double fCos)
2076 {
2077 	CheckReference();
2078 
2079 	for (sal_uInt16 i = 0; i < Count(); i++)
2080 		pImpXPolyPolygon->aXPolyList.GetObject(i)->SlantY(nXRef, fSin, fCos);
2081 }
2082 
2083 /*************************************************************************
2084 |*
2085 |*    XPolygon::Distort()
2086 |*
2087 |*    XPolygon verzerren, indem die Koordinaten relativ zu einem
2088 |*    Referenzrechteck in ein beliebiges Viereck skaliert werden
2089 |*    Zuordnung der Viereck-Punkte im Polygon zum Referenzrechteck:
2090 |*    0: links oben      0----1
2091 |*    1: rechts oben     |    |
2092 |*    2: rechts unten    3----2
2093 |*    3: links unten
2094 |*    Ersterstellung    ESO 07.07.95
2095 |*    Letzte Aenderung  ESO 07.07.95
2096 |*
2097 *************************************************************************/
2098 
2099 void XPolyPolygon::Distort(const Rectangle& rRefRect,
2100 						   const XPolygon& rDistortedRect)
2101 {
2102 	CheckReference();
2103 
2104 	for (sal_uInt16 i = 0; i < Count(); i++)
2105 		pImpXPolyPolygon->aXPolyList.GetObject(i)->Distort(rRefRect,
2106 														   rDistortedRect);
2107 }
2108 
2109 basegfx::B2DPolyPolygon XPolyPolygon::getB2DPolyPolygon() const
2110 {
2111 	basegfx::B2DPolyPolygon aRetval;
2112 
2113 	for(sal_uInt16 a(0L); a < Count(); a++)
2114 	{
2115 		const XPolygon& rPoly = (*this)[a];
2116 		aRetval.append(rPoly.getB2DPolygon());
2117 	}
2118 
2119 	return aRetval;
2120 }
2121 
2122 XPolyPolygon::XPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon)
2123 {
2124 	DBG_CTOR(XPolyPolygon,NULL);
2125 	pImpXPolyPolygon = new ImpXPolyPolygon( 16, 16 );
2126 
2127 	for(sal_uInt32 a(0L); a < rPolyPolygon.count(); a++)
2128 	{
2129 		basegfx::B2DPolygon aCandidate = rPolyPolygon.getB2DPolygon(a);
2130 		XPolygon aNewPoly(aCandidate);
2131 		Insert(aNewPoly);
2132 	}
2133 }
2134 
2135 // eof
2136