xref: /trunk/main/svx/source/xoutdev/_xpoly.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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