merge the formfield patch from ooo-build
[ooovba.git] / svx / source / xoutdev / _xpoly.cxx
blobab9f69d8c8d781808bbdbf379921a63519498ebe
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: _xpoly.cxx,v $
10 * $Revision: 1.19 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
33 #include <osl/endian.h>
34 #include <tools/stream.hxx>
35 #include <tools/debug.hxx>
36 #include <tools/poly.hxx>
38 #include <svx/xpoly.hxx>
39 #include "xpolyimp.hxx"
40 #include <basegfx/polygon/b2dpolygon.hxx>
41 #include <basegfx/point/b2dpoint.hxx>
42 #include <basegfx/vector/b2dvector.hxx>
43 #include <basegfx/polygon/b2dpolygontools.hxx>
44 #include <vcl/salbtype.hxx> // FRound
45 #include <basegfx/range/b2drange.hxx>
46 #include <basegfx/numeric/ftools.hxx>
48 #define GLOBALOVERFLOW
50 DBG_NAME(XPolygon);
51 DBG_NAME(XPolyPolygon);
53 /*************************************************************************
55 |* ImpXPolygon::ImpXPolygon()
57 |* Beschreibung
58 |* Ersterstellung 08.11.94
59 |* Letzte Aenderung 12.01.95 ESO
61 *************************************************************************/
63 ImpXPolygon::ImpXPolygon( USHORT nInitSize, USHORT _nResize )
65 pPointAry = NULL;
66 pFlagAry = NULL;
67 bDeleteOldPoints = FALSE;
68 nSize = 0;
69 nResize = _nResize;
70 nPoints = 0;
71 nRefCount = 1;
73 Resize( nInitSize );
76 /*************************************************************************
78 |* ImpXPolygon::ImpXPolygon()
80 |* Beschreibung
81 |* Ersterstellung 08.11.94
82 |* Letzte Aenderung 12.01.95 ESO
84 *************************************************************************/
86 ImpXPolygon::ImpXPolygon( const ImpXPolygon& rImpXPoly )
88 ( (ImpXPolygon&) rImpXPoly ).CheckPointDelete();
90 pPointAry = NULL;
91 pFlagAry = NULL;
92 bDeleteOldPoints = FALSE;
93 nSize = 0;
94 ImpXPolygon::nResize = rImpXPoly.nResize;
95 nPoints = 0;
96 nRefCount = 1;
98 Resize( rImpXPoly.nSize );
100 // Kopieren
101 nPoints = rImpXPoly.nPoints;
102 memcpy( pPointAry, rImpXPoly.pPointAry, nSize*sizeof( Point ) );
103 memcpy( pFlagAry, rImpXPoly.pFlagAry, nSize );
106 /*************************************************************************
108 |* ImpXPolygon::~ImpXPolygon()
110 |* Beschreibung
111 |* Ersterstellung 08.11.94
112 |* Letzte Aenderung 12.01.95 ESO
114 *************************************************************************/
116 ImpXPolygon::~ImpXPolygon()
118 delete[] (char*) pPointAry;
119 delete[] pFlagAry;
120 if ( bDeleteOldPoints )
121 delete[] (char*) pOldPointAry;
124 /*************************************************************************
126 |* ImpXPolygon::operator==()
128 |* Ersterstellung Joe 26-09-95
129 |* Letzte Aenderung
131 *************************************************************************/
134 bool ImpXPolygon::operator==(const ImpXPolygon& rImpXPoly) const
136 return nPoints==rImpXPoly.nPoints &&
137 (nPoints==0 ||
138 (memcmp(pPointAry,rImpXPoly.pPointAry,nPoints*sizeof(Point))==0 &&
139 memcmp(pFlagAry,rImpXPoly.pFlagAry,nPoints)==0));
142 /*************************************************************************
144 |* ImpXPolygon::Resize()
146 |* !!! Polygongroesse aendern - wenn bDeletePoints FALSE, dann den
147 |* Point-Array nicht loeschen, sondern in pOldPointAry sichern und
148 |* das Flag bDeleteOldPoints setzen. Beim naechsten Zugriff wird
149 |* das Array dann geloescht.
150 |* Damit wird verhindert, dass bei XPoly[n] = XPoly[0] durch ein
151 |* Resize der fuer den rechten Ausdruck verwendete Point-Array
152 |* vorzeitig geloescht wird.
153 |* Ersterstellung 08.11.94
154 |* Letzte Aenderung 12.01.95 ESO
156 *************************************************************************/
158 void ImpXPolygon::Resize( USHORT nNewSize, BOOL bDeletePoints )
160 if( nNewSize == nSize )
161 return;
163 BYTE* pOldFlagAry = pFlagAry;
164 USHORT nOldSize = nSize;
166 CheckPointDelete();
167 pOldPointAry = pPointAry;
169 // Neue Groesse auf vielfaches von nResize runden, sofern Objekt
170 // nicht neu angelegt wurde (nSize != 0)
171 if ( nSize != 0 && nNewSize > nSize )
173 DBG_ASSERT(nResize, "Resize-Versuch trotz nResize = 0 !");
174 nNewSize = nSize + ((nNewSize-nSize-1) / nResize + 1) * nResize;
176 // Punkt Array erzeugen
177 nSize = nNewSize;
178 pPointAry = (Point*)new char[ nSize*sizeof( Point ) ];
179 memset( pPointAry, 0, nSize*sizeof( Point ) );
181 // Flag Array erzeugen
182 pFlagAry = new BYTE[ nSize ];
183 memset( pFlagAry, 0, nSize );
185 // Eventuell umkopieren
186 if( nOldSize )
188 if( nOldSize < nSize )
190 memcpy( pPointAry, pOldPointAry, nOldSize*sizeof( Point ) );
191 memcpy( pFlagAry, pOldFlagAry, nOldSize );
193 else
195 memcpy( pPointAry, pOldPointAry, nSize*sizeof( Point ) );
196 memcpy( pFlagAry, pOldFlagAry, nSize );
198 // Anzahl der gueltigen Punkte anpassen
199 if( nPoints > nSize )
200 nPoints = nSize;
202 if ( bDeletePoints ) delete[] (char*) pOldPointAry;
203 else bDeleteOldPoints = TRUE;
204 delete[] pOldFlagAry;
209 /*************************************************************************
211 |* ImpXPolygon::InsertSpace()
213 |* Beschreibung
214 |* Ersterstellung 08.11.94
215 |* Letzte Aenderung 29.03.95 ESO
217 *************************************************************************/
219 void ImpXPolygon::InsertSpace( USHORT nPos, USHORT nCount )
221 CheckPointDelete();
223 if ( nPos > nPoints )
224 nPos = nPoints;
226 // Wenn Polygon zu klein dann groesser machen
227 if( (nPoints + nCount) > nSize )
228 Resize( nPoints + nCount );
230 // Wenn nicht hinter dem letzten Punkt eingefuegt wurde,
231 // den Rest nach hinten schieben
232 if( nPos < nPoints )
234 USHORT nMove = nPoints - nPos;
235 memmove( &pPointAry[nPos+nCount], &pPointAry[nPos],
236 nMove * sizeof(Point) );
237 memmove( &pFlagAry[nPos+nCount], &pFlagAry[nPos], nMove );
239 memset( &pPointAry[nPos], 0, nCount * sizeof( Point ) );
240 memset( &pFlagAry [nPos], 0, nCount );
242 nPoints = nPoints + nCount;
246 /*************************************************************************
248 |* ImpXPolygon::Remove()
250 |* Beschreibung
251 |* Ersterstellung 08.11.94
252 |* Letzte Aenderung 12.01.94 ESO
254 *************************************************************************/
256 void ImpXPolygon::Remove( USHORT nPos, USHORT nCount )
258 CheckPointDelete();
260 if( (nPos + nCount) <= nPoints )
262 USHORT nMove = nPoints - nPos - nCount;
264 if( nMove )
266 memmove( &pPointAry[nPos], &pPointAry[nPos+nCount],
267 nMove * sizeof(Point) );
268 memmove( &pFlagAry[nPos], &pFlagAry[nPos+nCount], nMove );
270 memset( &pPointAry[nPoints - nCount], 0, nCount * sizeof( Point ) );
271 memset( &pFlagAry [nPoints - nCount], 0, nCount );
272 nPoints = nPoints - nCount;
277 /*************************************************************************
279 |* XPolygon::XPolygon()
281 |* Beschreibung
282 |* Ersterstellung 08.11.94
283 |* Letzte Aenderung 08.11.94
285 *************************************************************************/
287 XPolygon::XPolygon( USHORT nSize, USHORT nResize )
289 DBG_CTOR(XPolygon,NULL);
290 pImpXPolygon = new ImpXPolygon( nSize, nResize );
293 /*************************************************************************
295 |* XPolygon::XPolygon()
297 |* Beschreibung
298 |* Ersterstellung 08.11.94
299 |* Letzte Aenderung 08.11.94
301 *************************************************************************/
303 XPolygon::XPolygon( const XPolygon& rXPoly )
305 DBG_CTOR(XPolygon,NULL);
306 pImpXPolygon = rXPoly.pImpXPolygon;
307 pImpXPolygon->nRefCount++;
310 /*************************************************************************
312 |* XPolygon::XPolygon()
314 |* XPolygon aus einem Standardpolygon erstellen
315 |* Ersterstellung 18.01.95 ESO
316 |* Letzte Aenderung 18.01.95 ESO
318 *************************************************************************/
320 XPolygon::XPolygon( const Polygon& rPoly )
322 DBG_CTOR(XPolygon,NULL);
324 USHORT nSize = rPoly.GetSize();
325 pImpXPolygon = new ImpXPolygon( nSize );
326 pImpXPolygon->nPoints = nSize;
328 for( USHORT i = 0; i < nSize; i++ )
330 pImpXPolygon->pPointAry[i] = rPoly[i];
331 pImpXPolygon->pFlagAry[i] = (BYTE) rPoly.GetFlags( i );
335 /*************************************************************************
337 |* XPolygon::XPolygon()
339 |* Rechteck (auch mit abgerundeten Ecken) als Bezierpolygon erzeugen
340 |* Ersterstellung 09.01.95 ESO
341 |* Letzte Aenderung 09.01.95 ESO
343 *************************************************************************/
345 XPolygon::XPolygon(const Rectangle& rRect, long nRx, long nRy)
347 DBG_CTOR(XPolygon,NULL);
348 pImpXPolygon = new ImpXPolygon(17);
349 long nWh = (rRect.GetWidth() - 1) / 2;
350 long nHh = (rRect.GetHeight() - 1) / 2;
352 if ( nRx > nWh ) nRx = nWh;
353 if ( nRy > nHh ) nRy = nHh;
355 // Rx negativ, damit Umlauf im Uhrzeigersinn erfolgt
356 nRx = -nRx;
358 // Faktor fuer Kontrollpunkte der Bezierkurven: 8/3 * (sin(45g) - 0.5)
359 long nXHdl = (long)(0.552284749 * nRx);
360 long nYHdl = (long)(0.552284749 * nRy);
361 USHORT nPos = 0;
363 if ( nRx && nRy )
365 Point aCenter;
367 for (USHORT nQuad = 0; nQuad < 4; nQuad++)
369 switch ( nQuad )
371 case 0: aCenter = rRect.TopLeft();
372 aCenter.X() -= nRx;
373 aCenter.Y() += nRy;
374 break;
375 case 1: aCenter = rRect.TopRight();
376 aCenter.X() += nRx;
377 aCenter.Y() += nRy;
378 break;
379 case 2: aCenter = rRect.BottomRight();
380 aCenter.X() += nRx;
381 aCenter.Y() -= nRy;
382 break;
383 case 3: aCenter = rRect.BottomLeft();
384 aCenter.X() -= nRx;
385 aCenter.Y() -= nRy;
386 break;
388 GenBezArc(aCenter, nRx, nRy, nXHdl, nYHdl, 0, 900, nQuad, nPos);
389 pImpXPolygon->pFlagAry[nPos ] = (BYTE) XPOLY_SMOOTH;
390 pImpXPolygon->pFlagAry[nPos+3] = (BYTE) XPOLY_SMOOTH;
391 nPos += 4;
394 else
396 pImpXPolygon->pPointAry[nPos++] = rRect.TopLeft();
397 pImpXPolygon->pPointAry[nPos++] = rRect.TopRight();
398 pImpXPolygon->pPointAry[nPos++] = rRect.BottomRight();
399 pImpXPolygon->pPointAry[nPos++] = rRect.BottomLeft();
401 pImpXPolygon->pPointAry[nPos] = pImpXPolygon->pPointAry[0];
402 pImpXPolygon->nPoints = nPos + 1;
405 /*************************************************************************
407 |* XPolygon::XPolygon()
409 |* Ellipsen(bogen) als Bezierpolygon erzeugen
410 |* Ersterstellung 09.01.95
411 |* Letzte Aenderung 09.01.95
413 *************************************************************************/
415 XPolygon::XPolygon(const Point& rCenter, long nRx, long nRy,
416 USHORT nStartAngle, USHORT nEndAngle, BOOL bClose)
418 DBG_CTOR(XPolygon,NULL);
419 pImpXPolygon = new ImpXPolygon(17);
421 nStartAngle %= 3600;
422 if ( nEndAngle > 3600 ) nEndAngle %= 3600;
423 BOOL bFull = (nStartAngle == 0 && nEndAngle == 3600);
425 // Faktor fuer Kontrollpunkte der Bezierkurven: 8/3 * (sin(45g) - 0.5)
426 long nXHdl = (long)(0.552284749 * nRx);
427 long nYHdl = (long)(0.552284749 * nRy);
428 USHORT nPos = 0;
429 BOOL bLoopEnd = FALSE;
433 USHORT nA1, nA2;
434 USHORT nQuad = nStartAngle / 900;
435 if ( nQuad == 4 ) nQuad = 0;
436 bLoopEnd = CheckAngles(nStartAngle, nEndAngle, nA1, nA2);
437 GenBezArc(rCenter, nRx, nRy, nXHdl, nYHdl, nA1, nA2, nQuad, nPos);
438 nPos += 3;
439 if ( !bLoopEnd )
440 pImpXPolygon->pFlagAry[nPos] = (BYTE) XPOLY_SMOOTH;
442 } while ( !bLoopEnd );
444 // Wenn kein Vollkreis, dann ggf. Enden mit Mittelpunkt verbinden
445 if ( !bFull && bClose )
446 pImpXPolygon->pPointAry[++nPos] = rCenter;
448 if ( bFull )
450 pImpXPolygon->pFlagAry[0 ] = (BYTE) XPOLY_SMOOTH;
451 pImpXPolygon->pFlagAry[nPos] = (BYTE) XPOLY_SMOOTH;
453 pImpXPolygon->nPoints = nPos + 1;
456 /*************************************************************************
458 |* XPolygon::~XPolygon()
460 |* Beschreibung
461 |* Ersterstellung 08.11.94
462 |* Letzte Aenderung 08.11.94
464 *************************************************************************/
466 XPolygon::~XPolygon()
468 DBG_DTOR(XPolygon,NULL);
469 if( pImpXPolygon->nRefCount > 1 )
470 pImpXPolygon->nRefCount--;
471 else
472 delete pImpXPolygon;
475 /*************************************************************************
477 |* XPolygon::CheckReference()
479 |* Referenzzaehler desImpXPoly pruefen und ggf. von diesem abkoppeln
480 |* Ersterstellung 17.01.95 ESO
481 |* Letzte Aenderung 17.01.95 ESO
483 *************************************************************************/
485 void XPolygon::CheckReference()
487 if( pImpXPolygon->nRefCount > 1 )
489 pImpXPolygon->nRefCount--;
490 pImpXPolygon = new ImpXPolygon( *pImpXPolygon );
494 /*************************************************************************
496 |* XPolygon::SetSize()
498 |* Beschreibung
499 |* Ersterstellung 08.11.94
500 |* Letzte Aenderung 08.11.94
502 *************************************************************************/
504 void XPolygon::SetSize( USHORT nNewSize )
506 CheckReference();
507 pImpXPolygon->Resize( nNewSize );
510 /*************************************************************************
512 |* XPolygon::GetSize()
514 |* Beschreibung
515 |* Ersterstellung 08.11.94
516 |* Letzte Aenderung 12.01.95 ESO
518 *************************************************************************/
520 USHORT XPolygon::GetSize() const
522 pImpXPolygon->CheckPointDelete();
523 return pImpXPolygon->nSize;
526 /*************************************************************************
528 |* XPolygon::SetPointCount()
530 |* Beschreibung
531 |* Ersterstellung 08.11.94
532 |* Letzte Aenderung 12.01.95 ESO
534 *************************************************************************/
536 void XPolygon::SetPointCount( USHORT nPoints )
538 pImpXPolygon->CheckPointDelete();
539 CheckReference();
541 if( pImpXPolygon->nSize < nPoints )
542 pImpXPolygon->Resize( nPoints );
544 if ( nPoints < pImpXPolygon->nPoints )
546 USHORT nSize = pImpXPolygon->nPoints - nPoints;
547 memset( &pImpXPolygon->pPointAry[nPoints], 0, nSize * sizeof( Point ) );
548 memset( &pImpXPolygon->pFlagAry [nPoints], 0, nSize );
550 pImpXPolygon->nPoints = nPoints;
553 /*************************************************************************
555 |* XPolygon::GetPointCount()
557 |* Beschreibung
558 |* Ersterstellung 08.11.94
559 |* Letzte Aenderung 12.01.95 ESO
561 *************************************************************************/
563 USHORT XPolygon::GetPointCount() const
565 pImpXPolygon->CheckPointDelete();
566 return pImpXPolygon->nPoints;
569 /*************************************************************************
571 |* XPolygon::Insert()
573 |* Beschreibung
574 |* Ersterstellung 08.11.94
575 |* Letzte Aenderung 08.11.94
577 *************************************************************************/
579 void XPolygon::Insert( USHORT nPos, const Point& rPt, XPolyFlags eFlags )
581 CheckReference();
582 if (nPos>pImpXPolygon->nPoints) nPos=pImpXPolygon->nPoints;
583 pImpXPolygon->InsertSpace( nPos, 1 );
584 pImpXPolygon->pPointAry[nPos] = rPt;
585 pImpXPolygon->pFlagAry[nPos] = (BYTE)eFlags;
588 /*************************************************************************
590 |* XPolygon::Insert()
592 |* Beschreibung
593 |* Ersterstellung 08.11.94
594 |* Letzte Aenderung 08.11.94
596 *************************************************************************/
598 void XPolygon::Insert( USHORT nPos, const XPolygon& rXPoly )
600 CheckReference();
601 if (nPos>pImpXPolygon->nPoints) nPos=pImpXPolygon->nPoints;
603 USHORT nPoints = rXPoly.GetPointCount();
605 pImpXPolygon->InsertSpace( nPos, nPoints );
607 memcpy( &(pImpXPolygon->pPointAry[nPos]),
608 rXPoly.pImpXPolygon->pPointAry,
609 nPoints*sizeof( Point ) );
610 memcpy( &(pImpXPolygon->pFlagAry[nPos]),
611 rXPoly.pImpXPolygon->pFlagAry,
612 nPoints );
615 /*************************************************************************
617 |* XPolygon::Insert()
619 |* Beschreibung
620 |* Ersterstellung 08.11.94
621 |* Letzte Aenderung 08.11.94
623 *************************************************************************/
625 void XPolygon::Insert( USHORT nPos, const Polygon& rPoly )
627 CheckReference();
628 if (nPos>pImpXPolygon->nPoints) nPos=pImpXPolygon->nPoints;
630 USHORT nPoints = rPoly.GetSize();
632 pImpXPolygon->InsertSpace( nPos, nPoints );
634 USHORT i;
635 for( i=0; i < nPoints; i++ )
636 pImpXPolygon->pPointAry[i] = rPoly[i];
638 // Die Flags sind durch das InsertSpace bereits auf 0 gesetzt
641 /*************************************************************************
643 |* XPolygon::Remove()
645 |* Beschreibung
646 |* Ersterstellung 08.11.94
647 |* Letzte Aenderung 08.11.94
649 *************************************************************************/
651 void XPolygon::Remove( USHORT nPos, USHORT nCount )
653 CheckReference();
654 pImpXPolygon->Remove( nPos, nCount );
657 /*************************************************************************
659 |* XPolygon::Move()
661 |* Beschreibung
662 |* Ersterstellung 09.11.94
663 |* Letzte Aenderung 09.11.94
665 *************************************************************************/
667 void XPolygon::Move( long nHorzMove, long nVertMove )
669 if ( !nHorzMove && !nVertMove )
670 return;
672 CheckReference();
674 // Punkte verschieben
675 USHORT nCount = pImpXPolygon->nPoints;
676 for ( USHORT i = 0; i < nCount; i++ )
678 Point* pPt = &(pImpXPolygon->pPointAry[i]);
679 pPt->X() += nHorzMove;
680 pPt->Y() += nVertMove;
684 /*************************************************************************
686 |* XPolygon::GetBoundRect()
688 |* Beschreibung
689 |* Ersterstellung 09.11.94
690 |* Letzte Aenderung 12.01.95 ESO
692 *************************************************************************/
694 Rectangle XPolygon::GetBoundRect() const
696 pImpXPolygon->CheckPointDelete();
697 Rectangle aRetval;
699 if(pImpXPolygon->nPoints)
701 // #i37709#
702 // For historical reasons the control points are not part of the
703 // BoundRect. This makes it necessary to subdivide the polygon to
704 // get a relatively correct BoundRect. Numerically, this is not
705 // correct and never was.
707 const basegfx::B2DRange aPolygonRange(basegfx::tools::getRange(getB2DPolygon()));
708 aRetval = Rectangle(
709 FRound(aPolygonRange.getMinX()), FRound(aPolygonRange.getMinY()),
710 FRound(aPolygonRange.getMaxX()), FRound(aPolygonRange.getMaxY()));
713 return aRetval;
716 /*************************************************************************
718 |* XPolygon::operator[]()
720 |* Beschreibung
721 |* Ersterstellung 08.11.94
722 |* Letzte Aenderung 12.01.95
724 *************************************************************************/
726 const Point& XPolygon::operator[]( USHORT nPos ) const
728 DBG_ASSERT(nPos < pImpXPolygon->nPoints, "Ungueltiger Index bei const-Arrayzugriff auf XPolygon");
730 pImpXPolygon->CheckPointDelete();
731 return pImpXPolygon->pPointAry[nPos];
734 /*************************************************************************
736 |* XPolygon::operator[]()
738 |* Beschreibung
739 |* Ersterstellung 08.11.94
740 |* Letzte Aenderung 12.01.95 ESO
742 *************************************************************************/
744 Point& XPolygon::operator[]( USHORT nPos )
746 pImpXPolygon->CheckPointDelete();
747 CheckReference();
749 if( nPos >= pImpXPolygon->nSize )
751 DBG_ASSERT(pImpXPolygon->nResize, "Ungueltiger Index bei Arrayzugriff auf XPolygon");
752 pImpXPolygon->Resize(nPos + 1, FALSE);
754 if( nPos >= pImpXPolygon->nPoints )
755 pImpXPolygon->nPoints = nPos + 1;
757 return pImpXPolygon->pPointAry[nPos];
760 /*************************************************************************
762 |* XPolygon::operator=()
764 |* Beschreibung Zuweisungsoperator
765 |* Ersterstellung ESO 22.11.94
766 |* Letzte Aenderung ESO 12.01.95
768 *************************************************************************/
770 XPolygon& XPolygon::operator=( const XPolygon& rXPoly )
772 pImpXPolygon->CheckPointDelete();
774 rXPoly.pImpXPolygon->nRefCount++;
776 if( pImpXPolygon->nRefCount > 1 )
777 pImpXPolygon->nRefCount--;
778 else
779 delete pImpXPolygon;
781 pImpXPolygon = rXPoly.pImpXPolygon;
782 return *this;
785 /*************************************************************************
787 |* XPolygon::operator==()
789 |* Beschreibung Gleichheitsoperator
790 |* Ersterstellung ESO 22.11.94
791 |* Letzte Aenderung Joe 26.09.95
793 *************************************************************************/
795 BOOL XPolygon::operator==( const XPolygon& rXPoly ) const
797 pImpXPolygon->CheckPointDelete();
798 if (rXPoly.pImpXPolygon==pImpXPolygon) return TRUE;
799 return *rXPoly.pImpXPolygon == *pImpXPolygon;
802 /*************************************************************************
804 |* XPolygon::operator!=()
806 |* Beschreibung Ungleichheitsoperator
807 |* Ersterstellung ESO 22.11.94
808 |* Letzte Aenderung Joe 26.09.95
810 *************************************************************************/
812 BOOL XPolygon::operator!=( const XPolygon& rXPoly ) const
814 pImpXPolygon->CheckPointDelete();
815 if (rXPoly.pImpXPolygon==pImpXPolygon) return FALSE;
816 return *rXPoly.pImpXPolygon != *pImpXPolygon;
819 /*************************************************************************
821 |* XPolygon::GetFlags()
823 |* Flags fuer den Punkt an der Position nPos zurueckgeben
824 |* Ersterstellung ESO 11.11.94
825 |* Letzte Aenderung ESO 12.01.95
827 *************************************************************************/
829 XPolyFlags XPolygon::GetFlags( USHORT nPos ) const
831 pImpXPolygon->CheckPointDelete();
832 return (XPolyFlags) pImpXPolygon->pFlagAry[nPos];
835 /*************************************************************************
837 |* XPolygon::SetFlags()
839 |* Flags fuer den Punkt an der Position nPos setzen
840 |* Ersterstellung ESO 11.11.94
841 |* Letzte Aenderung ESO 12.01.95
843 *************************************************************************/
845 void XPolygon::SetFlags( USHORT nPos, XPolyFlags eFlags )
847 pImpXPolygon->CheckPointDelete();
848 CheckReference();
849 pImpXPolygon->pFlagAry[nPos] = (BYTE) eFlags;
852 /*************************************************************************
854 |* XPolygon::IsControl()
856 |* Kurzform zur Abfrage des CONTROL-Flags
857 |* Ersterstellung ESO 09.01.95
858 |* Letzte Aenderung ESO 12.01.95
860 *************************************************************************/
862 BOOL XPolygon::IsControl(USHORT nPos) const
864 return ( (XPolyFlags) pImpXPolygon->pFlagAry[nPos] == XPOLY_CONTROL );
867 /*************************************************************************
869 |* XPolygon::IsSmooth()
871 |* Kurzform zur Abfrage von SMOOTH- und SYMMTR-Flag
872 |* Ersterstellung ESO 18.04.95
873 |* Letzte Aenderung ESO 18.04.95
875 *************************************************************************/
877 BOOL XPolygon::IsSmooth(USHORT nPos) const
879 XPolyFlags eFlag = (XPolyFlags) pImpXPolygon->pFlagAry[nPos];
880 return ( eFlag == XPOLY_SMOOTH || eFlag == XPOLY_SYMMTR );
883 /*************************************************************************
885 |* XPolygon::CalcDistance()
887 |* Abstand zwischen zwei Punkten berechnen
888 |* Ersterstellung ESO 09.01.95
889 |* Letzte Aenderung ESO 09.01.95
891 *************************************************************************/
893 double XPolygon::CalcDistance(USHORT nP1, USHORT nP2)
895 const Point& rP1 = pImpXPolygon->pPointAry[nP1];
896 const Point& rP2 = pImpXPolygon->pPointAry[nP2];
897 double fDx = rP2.X() - rP1.X();
898 double fDy = rP2.Y() - rP1.Y();
899 return sqrt(fDx * fDx + fDy * fDy);
902 /*************************************************************************
904 |* XPolygon::SubdivideBezier()
906 |* Bezierkurve unterteilen
907 |* Ersterstellung ESO 09.01.95
908 |* Letzte Aenderung ESO 09.01.95
910 *************************************************************************/
912 void XPolygon::SubdivideBezier(USHORT nPos, BOOL bCalcFirst, double fT)
914 Point* pPoints = pImpXPolygon->pPointAry;
915 double fT2 = fT * fT;
916 double fT3 = fT * fT2;
917 double fU = 1.0 - fT;
918 double fU2 = fU * fU;
919 double fU3 = fU * fU2;
920 USHORT nIdx = nPos;
921 short nPosInc, nIdxInc;
923 if ( bCalcFirst )
925 nPos += 3;
926 nPosInc = -1;
927 nIdxInc = 0;
929 else
931 nPosInc = 1;
932 nIdxInc = 1;
934 pPoints[nPos].X() = (long) (fU3 * pPoints[nIdx ].X() +
935 fT * fU2 * pPoints[nIdx+1].X() * 3 +
936 fT2 * fU * pPoints[nIdx+2].X() * 3 +
937 fT3 * pPoints[nIdx+3].X());
938 pPoints[nPos].Y() = (long) (fU3 * pPoints[nIdx ].Y() +
939 fT * fU2 * pPoints[nIdx+1].Y() * 3 +
940 fT2 * fU * pPoints[nIdx+2].Y() * 3 +
941 fT3 * pPoints[nIdx+3].Y());
942 nPos = nPos + nPosInc;
943 nIdx = nIdx + nIdxInc;
944 pPoints[nPos].X() = (long) (fU2 * pPoints[nIdx ].X() +
945 fT * fU * pPoints[nIdx+1].X() * 2 +
946 fT2 * pPoints[nIdx+2].X());
947 pPoints[nPos].Y() = (long) (fU2 * pPoints[nIdx ].Y() +
948 fT * fU * pPoints[nIdx+1].Y() * 2 +
949 fT2 * pPoints[nIdx+2].Y());
950 nPos = nPos + nPosInc;
951 nIdx = nIdx + nIdxInc;
952 pPoints[nPos].X() = (long) (fU * pPoints[nIdx ].X() +
953 fT * pPoints[nIdx+1].X());
954 pPoints[nPos].Y() = (long) (fU * pPoints[nIdx ].Y() +
955 fT * pPoints[nIdx+1].Y());
958 /************************************************************************/
960 void XPolygon::GenBezArc(const Point& rCenter, long nRx, long nRy,
961 long nXHdl, long nYHdl, USHORT nStart, USHORT nEnd,
962 USHORT nQuad, USHORT nFirst)
964 Point* pPoints = pImpXPolygon->pPointAry;
965 pPoints[nFirst ] = rCenter;
966 pPoints[nFirst+3] = rCenter;
968 if ( nQuad == 1 || nQuad == 2 )
970 nRx = -nRx; nXHdl = -nXHdl;
972 if ( nQuad == 0 || nQuad == 1 )
974 nRy = -nRy; nYHdl = -nYHdl;
977 if ( nQuad == 0 || nQuad == 2 )
979 pPoints[nFirst].X() += nRx; pPoints[nFirst+3].Y() += nRy;
981 else
983 pPoints[nFirst].Y() += nRy; pPoints[nFirst+3].X() += nRx;
985 pPoints[nFirst+1] = pPoints[nFirst];
986 pPoints[nFirst+2] = pPoints[nFirst+3];
988 if ( nQuad == 0 || nQuad == 2 )
990 pPoints[nFirst+1].Y() += nYHdl; pPoints[nFirst+2].X() += nXHdl;
992 else
994 pPoints[nFirst+1].X() += nXHdl; pPoints[nFirst+2].Y() += nYHdl;
996 if ( nStart > 0 )
997 SubdivideBezier(nFirst, FALSE, (double)nStart / 900);
998 if ( nEnd < 900 )
999 SubdivideBezier(nFirst, TRUE, (double)(nEnd-nStart) / (900-nStart));
1000 SetFlags(nFirst+1, XPOLY_CONTROL);
1001 SetFlags(nFirst+2, XPOLY_CONTROL);
1004 /************************************************************************/
1006 BOOL XPolygon::CheckAngles(USHORT& nStart, USHORT nEnd, USHORT& nA1, USHORT& nA2)
1008 if ( nStart == 3600 ) nStart = 0;
1009 if ( nEnd == 0 ) nEnd = 3600;
1010 USHORT nStPrev = nStart;
1011 USHORT nMax = (nStart / 900 + 1) * 900;
1012 USHORT nMin = nMax - 900;
1014 if ( nEnd >= nMax || nEnd <= nStart ) nA2 = 900;
1015 else nA2 = nEnd - nMin;
1016 nA1 = nStart - nMin;
1017 nStart = nMax;
1019 // TRUE zurueck, falls letztes Segment berechnet wurde
1020 return (nStPrev < nEnd && nStart >= nEnd);
1023 /*************************************************************************
1025 |* XPolygon::CalcSmoothJoin()
1027 |* glatten Uebergang zu einer Bezierkurve berechnen, indem der
1028 |* entsprechende Punkt auf die Verbindungslinie von zwei anderen
1029 |* Punkten projiziert wird
1030 |* Center = End- bzw. Anfangspunkt der Bezierkurve
1031 |* Drag = der bewegte Punkt, der die Verschiebung von Pnt vorgibt
1032 |* Pnt = der zu modifizierende Punkt
1033 |* Wenn Center am Anfang bzw. Ende des Polygons liegt, wird Pnt
1034 |* auf die entgegengesetzte Seite verlegt
1035 |* Ersterstellung ESO 09.01.95
1036 |* Letzte Aenderung ESO 18.04.95
1038 \************************************************************************/
1040 void XPolygon::CalcSmoothJoin(USHORT nCenter, USHORT nDrag, USHORT nPnt)
1042 CheckReference();
1044 // USHORT nMaxPnt = pImpXPolygon->nPoints - 1;
1046 // if ( nCenter == nMaxPnt ) nPnt = 1;
1047 // else if ( nCenter == 0 ) nPnt = nMaxPnt - 1;
1049 // Wenn nPnt kein Control-Punkt, d.h. nicht verschiebbar, dann
1050 // statt dessen nDrag auf der Achse nCenter-nPnt verschieben
1051 if ( !IsControl(nPnt) )
1053 USHORT nTmp = nDrag;
1054 nDrag = nPnt;
1055 nPnt = nTmp;
1057 Point* pPoints = pImpXPolygon->pPointAry;
1058 Point aDiff = pPoints[nDrag] - pPoints[nCenter];
1059 double fDiv = CalcDistance(nCenter, nDrag);
1061 if ( fDiv )
1063 double fRatio = CalcDistance(nCenter, nPnt) / fDiv;
1064 // bei SMOOTH bisherige Laenge beibehalten
1065 if ( GetFlags(nCenter) == XPOLY_SMOOTH || !IsControl(nDrag) )
1067 aDiff.X() = (long) (fRatio * aDiff.X());
1068 aDiff.Y() = (long) (fRatio * aDiff.Y());
1070 pPoints[nPnt] = pPoints[nCenter] - aDiff;
1074 /*************************************************************************
1076 |* XPolygon::CalcTangent()
1078 |* Tangente fuer den Uebergang zwischen zwei Bezierkurven berechnen
1079 |* Center = End- bzw. Anfangspunkt der Bezierkurven
1080 |* Prev = vorheriger Zugpunkt
1081 |* Next = naechster Zugpunkt
1082 |* Ersterstellung ESO 09.01.95
1083 |* Letzte Aenderung ESO 18.04.95
1085 \************************************************************************/
1087 void XPolygon::CalcTangent(USHORT nCenter, USHORT nPrev, USHORT nNext)
1089 CheckReference();
1091 double fAbsLen = CalcDistance(nNext, nPrev);
1093 if ( fAbsLen )
1095 const Point& rCenter = pImpXPolygon->pPointAry[nCenter];
1096 Point& rNext = pImpXPolygon->pPointAry[nNext];
1097 Point& rPrev = pImpXPolygon->pPointAry[nPrev];
1098 Point aDiff = rNext - rPrev;
1099 double fNextLen = CalcDistance(nCenter, nNext) / fAbsLen;
1100 double fPrevLen = CalcDistance(nCenter, nPrev) / fAbsLen;
1102 // bei SYMMTR gleiche Laenge fuer beide Seiten
1103 if ( GetFlags(nCenter) == XPOLY_SYMMTR )
1105 fPrevLen = (fNextLen + fPrevLen) / 2;
1106 fNextLen = fPrevLen;
1108 rNext.X() = rCenter.X() + (long) (fNextLen * aDiff.X());
1109 rNext.Y() = rCenter.Y() + (long) (fNextLen * aDiff.Y());
1110 rPrev.X() = rCenter.X() - (long) (fPrevLen * aDiff.X());
1111 rPrev.Y() = rCenter.Y() - (long) (fPrevLen * aDiff.Y());
1115 /*************************************************************************
1117 |* XPolygon::PointsToBezier()
1119 |* wandelt vier Polygonpunkte in eine Bezierkurve durch diese Punkte um
1120 |* Ersterstellung ESO 09.01.95
1121 |* Letzte Aenderung ESO 09.01.95
1123 \************************************************************************/
1125 void XPolygon::PointsToBezier(USHORT nFirst)
1127 double nFullLength, nPart1Length, nPart2Length;
1128 double fX0, fY0, fX1, fY1, fX2, fY2, fX3, fY3;
1129 double fTx1, fTx2, fTy1, fTy2;
1130 double fT1, fU1, fT2, fU2, fV;
1131 Point* pPoints = pImpXPolygon->pPointAry;
1133 if ( nFirst > pImpXPolygon->nPoints - 4 || IsControl(nFirst) ||
1134 IsControl(nFirst+1) || IsControl(nFirst+2) || IsControl(nFirst+3) )
1135 return;
1137 CheckReference();
1139 fTx1 = pPoints[nFirst+1].X();
1140 fTy1 = pPoints[nFirst+1].Y();
1141 fTx2 = pPoints[nFirst+2].X();
1142 fTy2 = pPoints[nFirst+2].Y();
1143 fX0 = pPoints[nFirst ].X();
1144 fY0 = pPoints[nFirst ].Y();
1145 fX3 = pPoints[nFirst+3].X();
1146 fY3 = pPoints[nFirst+3].Y();
1148 nPart1Length = CalcDistance(nFirst, nFirst+1);
1149 nPart2Length = nPart1Length + CalcDistance(nFirst+1, nFirst+2);
1150 nFullLength = nPart2Length + CalcDistance(nFirst+2, nFirst+3);
1151 if ( nFullLength < 20 )
1152 return;
1154 if ( nPart2Length == nFullLength )
1155 nPart2Length -= 1;
1156 if ( nPart1Length == nFullLength )
1157 nPart1Length = nPart2Length - 1;
1158 if ( nPart1Length <= 0 )
1159 nPart1Length = 1;
1160 if ( nPart2Length <= 0 || nPart2Length == nPart1Length )
1161 nPart2Length = nPart1Length + 1;
1163 fT1 = nPart1Length / nFullLength;
1164 fU1 = 1.0 - fT1;
1165 fT2 = nPart2Length / nFullLength;
1166 fU2 = 1.0 - fT2;
1167 fV = 3 * (1.0 - (fT1 * fU2) / (fT2 * fU1));
1169 fX1 = fTx1 / (fT1 * fU1 * fU1) - fTx2 * fT1 / (fT2 * fT2 * fU1 * fU2);
1170 fX1 /= fV;
1171 fX1 -= fX0 * ( fU1 / fT1 + fU2 / fT2) / 3;
1172 fX1 += fX3 * ( fT1 * fT2 / (fU1 * fU2)) / 3;
1174 fY1 = fTy1 / (fT1 * fU1 * fU1) - fTy2 * fT1 / (fT2 * fT2 * fU1 * fU2);
1175 fY1 /= fV;
1176 fY1 -= fY0 * ( fU1 / fT1 + fU2 / fT2) / 3;
1177 fY1 += fY3 * ( fT1 * fT2 / (fU1 * fU2)) / 3;
1179 fX2 = fTx2 / (fT2 * fT2 * fU2 * 3) - fX0 * fU2 * fU2 / ( fT2 * fT2 * 3);
1180 fX2 -= fX1 * fU2 / fT2;
1181 fX2 -= fX3 * fT2 / (fU2 * 3);
1183 fY2 = fTy2 / (fT2 * fT2 * fU2 * 3) - fY0 * fU2 * fU2 / ( fT2 * fT2 * 3);
1184 fY2 -= fY1 * fU2 / fT2;
1185 fY2 -= fY3 * fT2 / (fU2 * 3);
1187 pPoints[nFirst+1] = Point((long) fX1, (long) fY1);
1188 pPoints[nFirst+2] = Point((long) fX2, (long) fY2);
1189 SetFlags(nFirst+1, XPOLY_CONTROL);
1190 SetFlags(nFirst+2, XPOLY_CONTROL);
1193 /*************************************************************************
1195 |* XPolygon::Translate()
1197 |* Polygon auf den uebergebenen Punkt verschieben
1198 |* Ersterstellung ESO 17.01.95
1199 |* Letzte Aenderung ESO 17.01.95
1201 *************************************************************************/
1203 void XPolygon::Translate(const Point& rTrans)
1205 pImpXPolygon->CheckPointDelete();
1206 CheckReference();
1208 USHORT nPntCnt = pImpXPolygon->nPoints;
1210 for (USHORT i = 0; i < nPntCnt; i++)
1211 pImpXPolygon->pPointAry[i] += rTrans;
1214 /*************************************************************************
1216 |* XPolygon::Rotate()
1218 |* Alle Punkte um den Punkt rCenter drehen, Sinus und Cosinus
1219 |* muessen uebergeben werden
1220 |* Ersterstellung ESO 09.01.95
1221 |* Letzte Aenderung ESO 17.01.95
1223 *************************************************************************/
1225 void XPolygon::Rotate(const Point& rCenter, double fSin, double fCos)
1227 pImpXPolygon->CheckPointDelete();
1228 CheckReference();
1230 long nX;
1231 long nY;
1232 long nNewX;
1233 long nNewY;
1234 long nCenterX = rCenter.X();
1235 long nCenterY = rCenter.Y();
1237 USHORT nPntCnt = pImpXPolygon->nPoints;
1239 for (USHORT i = 0; i < nPntCnt; i++)
1241 Point *pPt = &(pImpXPolygon->pPointAry[i]);
1242 nX = pPt->X()-nCenterX;
1243 nY = pPt->Y()-nCenterY;
1244 nNewX = (long)floor(fCos * nX + fSin * nY + 0.5);
1245 nNewY = -(long)floor(fSin * nX - fCos * nY + 0.5);
1246 pPt->X() = nNewX + nCenterX;
1247 pPt->Y() = nNewY + nCenterY;
1249 /* und so stand das in einem anderen File auf T:
1250 dass ich am 29-11-1995 gegettet habe. Joe M.
1251 USHORT nPntCnt = pImpXPolygon->nPoints;
1253 for (USHORT i = 0; i < nPntCnt; i++)
1255 Point P = pImpXPolygon->pPointAry[i] - rCenter;
1256 long X = P.X();
1257 long Y = P.Y();
1258 P.X() = (long)floor(fCos * X + fSin * Y + 0.5);
1259 P.Y() = -(long)floor(fSin * X - fCos * Y + 0.5);
1260 pImpXPolygon->pPointAry[i] = P + rCenter;
1265 /*************************************************************************
1267 |* XPolygon::Rotate()
1269 |* Alle Punkte um den Punkt rCenter mit dem Winkel nAngle drehen
1270 |* Winkel in 10tel Grad, Wertebereich 0 - 3600
1271 |* Ersterstellung ESO 17.01.95
1272 |* Letzte Aenderung ESO 17.01.95
1274 *************************************************************************/
1276 void XPolygon::Rotate(const Point& rCenter, USHORT nAngle)
1278 nAngle %= 3600;
1280 if ( nAngle != 0 )
1282 double fAngle = F_PI * nAngle / 1800;
1283 double fSin = sin(fAngle);
1284 double fCos = cos(fAngle);
1285 Rotate(rCenter, fSin, fCos);
1289 /*************************************************************************
1291 |* XPolygon::Scale()
1293 |* XPolygon in X- und/oder Y-Richtung skalieren
1294 |* Ersterstellung ESO 01.02.95
1295 |* Letzte Aenderung ESO 01.02.95
1297 *************************************************************************/
1299 void XPolygon::Scale(double fSx, double fSy)
1301 pImpXPolygon->CheckPointDelete();
1302 CheckReference();
1304 USHORT nPntCnt = pImpXPolygon->nPoints;
1306 for (USHORT i = 0; i < nPntCnt; i++)
1308 Point& rPnt = pImpXPolygon->pPointAry[i];
1309 rPnt.X() = (long)(fSx * rPnt.X());
1310 rPnt.Y() = (long)(fSy * rPnt.Y());
1314 /*************************************************************************
1316 |* XPolygon::SlantX()
1318 |* XPolygon in X-Richtung um einen beliebigen Winkel kippen,
1319 |* bezogen auf eine Referenz-Y-Koordinate
1320 |* Ersterstellung ESO 01.02.95
1321 |* Letzte Aenderung ESO 01.02.95
1323 *************************************************************************/
1325 void XPolygon::SlantX(long nYRef, double fSin, double fCos)
1327 pImpXPolygon->CheckPointDelete();
1328 CheckReference();
1330 USHORT nPntCnt = pImpXPolygon->nPoints;
1332 for (USHORT i = 0; i < nPntCnt; i++)
1334 Point& rPnt = pImpXPolygon->pPointAry[i];
1335 long nDy = rPnt.Y() - nYRef;
1336 rPnt.X() += (long)(fSin * nDy);
1337 rPnt.Y() = nYRef + (long)(fCos * nDy);
1341 /*************************************************************************
1343 |* XPolygon::SlantY()
1345 |* XPolygon in Y-Richtung um einen beliebigen Winkel kippen,
1346 |* bezogen auf eine Referenz-X-Koordinate
1347 |* Ersterstellung ESO 01.02.95
1348 |* Letzte Aenderung ESO 01.02.95
1350 *************************************************************************/
1352 void XPolygon::SlantY(long nXRef, double fSin, double fCos)
1354 pImpXPolygon->CheckPointDelete();
1355 CheckReference();
1357 USHORT nPntCnt = pImpXPolygon->nPoints;
1359 for (USHORT i = 0; i < nPntCnt; i++)
1361 Point& rPnt = pImpXPolygon->pPointAry[i];
1362 long nDx = rPnt.X() - nXRef;
1363 rPnt.X() = nXRef + (long)(fCos * nDx);
1364 rPnt.Y() -= (long)(fSin * nDx);
1368 /*************************************************************************
1370 |* XPolygon::Distort()
1372 |* XPolygon verzerren, indem die Koordinaten relativ zu einem
1373 |* Referenzrechteck in ein beliebiges Viereck skaliert werden
1374 |* Zuordnung der Viereck-Punkte im Polygon zum Referenzrechteck:
1375 |* 0: links oben 0----1
1376 |* 1: rechts oben | |
1377 |* 2: rechts unten 3----2
1378 |* 3: links unten
1379 |* Ersterstellung ESO 07.07.95
1380 |* Letzte Aenderung ESO 07.07.95
1382 *************************************************************************/
1384 void XPolygon::Distort(const Rectangle& rRefRect,
1385 const XPolygon& rDistortedRect)
1387 pImpXPolygon->CheckPointDelete();
1388 CheckReference();
1390 long Xr, Wr, X1, X2, X3, X4;
1391 long Yr, Hr, Y1, Y2, Y3, Y4;
1392 double fTx, fTy, fUx, fUy;
1394 Xr = rRefRect.Left();
1395 Yr = rRefRect.Top();
1396 Wr = rRefRect.GetWidth();
1397 Hr = rRefRect.GetHeight();
1399 if ( Wr && Hr )
1401 DBG_ASSERT(rDistortedRect.pImpXPolygon->nPoints >= 4,
1402 "Distort-Rechteck zu klein");
1404 X1 = rDistortedRect[0].X();
1405 Y1 = rDistortedRect[0].Y();
1406 X2 = rDistortedRect[1].X();
1407 Y2 = rDistortedRect[1].Y();
1408 X3 = rDistortedRect[3].X();
1409 Y3 = rDistortedRect[3].Y();
1410 X4 = rDistortedRect[2].X();
1411 Y4 = rDistortedRect[2].Y();
1413 USHORT nPntCnt = pImpXPolygon->nPoints;
1415 for (USHORT i = 0; i < nPntCnt; i++)
1417 Point& rPnt = pImpXPolygon->pPointAry[i];
1419 fTx = (double)(rPnt.X() - Xr) / Wr;
1420 fTy = (double)(rPnt.Y() - Yr) / Hr;
1421 fUx = 1.0 - fTx;
1422 fUy = 1.0 - fTy;
1424 rPnt.X() = (long) ( fUy * (fUx * X1 + fTx * X2) +
1425 fTy * (fUx * X3 + fTx * X4) );
1426 rPnt.Y() = (long) ( fUx * (fUy * Y1 + fTy * Y3) +
1427 fTx * (fUy * Y2 + fTy * Y4) );
1432 /*************************************************************************
1434 |* Bestimme den linken, unteren Punkt des Polygons und richte das
1435 |* Polygon so aus, dass dieser Punkt auf dem Index 0 liegt
1437 \************************************************************************/
1439 void XPolygon::Rotate20()
1441 pImpXPolygon->CheckPointDelete();
1442 CheckReference();
1444 double fMinY = pImpXPolygon->pPointAry->Y();
1445 double fMinX = pImpXPolygon->pPointAry->X();
1446 long nPntCnt = pImpXPolygon->nPoints;
1447 long nIndex0 = 0;
1449 for (long nPoints = 1;
1450 nPoints < nPntCnt;
1451 nPoints ++)
1453 Point &rPnt = pImpXPolygon->pPointAry[nPoints];
1455 if ((rPnt.X () < fMinX) || (fMinX == rPnt.X ()) &&
1456 (fMinY >= rPnt.Y ()))
1458 fMinX = rPnt.X ();
1459 fMinY = rPnt.Y ();
1460 nIndex0 = nPoints;
1464 if (nIndex0 < nPntCnt)
1466 Point *pTemp = new Point [nIndex0];
1467 memcpy (pTemp, pImpXPolygon->pPointAry, nIndex0 * sizeof (Point));
1468 memcpy (pImpXPolygon->pPointAry, &pImpXPolygon->pPointAry [nIndex0], (nPntCnt - nIndex0) * sizeof (Point));
1469 memcpy (&pImpXPolygon->pPointAry [nIndex0], pTemp, nIndex0 * sizeof (Point));
1470 delete[] pTemp;
1474 basegfx::B2DPolygon XPolygon::getB2DPolygon() const
1476 // #i74631# use tools Polygon class for conversion to not have the code doubled
1477 // here. This needs one more conversion but avoids different convertors in
1478 // the long run
1479 DBG_ASSERT(pImpXPolygon != 0, "XPolygon::getB2DPolygon(): XPolygon has no implementation incarnated (!)");
1480 const Polygon aSource(GetPointCount(), pImpXPolygon->pPointAry, pImpXPolygon->pFlagAry);
1482 return aSource.getB2DPolygon();
1485 XPolygon::XPolygon(const basegfx::B2DPolygon& rPolygon)
1487 // #i74631# use tools Polygon class for conversion to not have the code doubled
1488 // here. This needs one more conversion but avoids different convertors in
1489 // the long run
1490 DBG_CTOR(XPolygon,NULL);
1492 const Polygon aSource(rPolygon);
1493 USHORT nSize = aSource.GetSize();
1494 pImpXPolygon = new ImpXPolygon( nSize );
1495 pImpXPolygon->nPoints = nSize;
1497 for( USHORT i = 0; i < nSize; i++ )
1499 pImpXPolygon->pPointAry[i] = aSource[i];
1500 pImpXPolygon->pFlagAry[i] = (BYTE) aSource.GetFlags( i );
1504 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1505 //+--------------- XPolyPolygon -----------------------------------------+
1506 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1508 /*************************************************************************
1510 |* ImpXPolyPolygon::ImpXPolyPolygon()
1512 |* Beschreibung Erzeugt das XPolygon-Array
1513 |* Ersterstellung CL 09.11.94
1514 |* Letzte Aenderung MM 09.11.94
1516 *************************************************************************/
1518 ImpXPolyPolygon::ImpXPolyPolygon( const ImpXPolyPolygon& rImpXPolyPoly ) :
1519 aXPolyList( rImpXPolyPoly.aXPolyList )
1521 nRefCount = 1;
1523 // Einzelne Elemente duplizieren
1524 XPolygon* pXPoly = aXPolyList.First();
1525 while ( pXPoly )
1527 aXPolyList.Replace( new XPolygon( *(aXPolyList.GetCurObject()) ) );
1528 pXPoly = aXPolyList.Next();
1533 /*************************************************************************
1535 |* ImpXPolyPolygon::~ImpXPolyPolygon()
1537 |* Beschreibung Loescht das Polygon-Array
1538 |* Ersterstellung CL 09.06.93
1539 |* Letzte Aenderung CL 09.06.93
1541 *************************************************************************/
1543 ImpXPolyPolygon::~ImpXPolyPolygon()
1545 XPolygon* pXPoly = aXPolyList.First();
1546 while( pXPoly )
1548 delete pXPoly;
1549 pXPoly = aXPolyList.Next();
1553 /*************************************************************************
1555 |* ImpXPolyPolygon::operator==()
1557 |* Ersterstellung Joe 26-09-95
1558 |* Letzte Aenderung
1560 *************************************************************************/
1563 bool ImpXPolyPolygon::operator==(const ImpXPolyPolygon& rImpXPolyPoly) const
1565 USHORT nAnz=(USHORT)aXPolyList.Count();
1566 const XPolygonList& rCmpList=rImpXPolyPoly.aXPolyList;
1567 if (nAnz!=(USHORT)rCmpList.Count()) return FALSE;
1568 bool bEq=true;
1569 for (USHORT i=nAnz; i>0 && bEq;) {
1570 i--;
1571 bEq= *aXPolyList.GetObject(i) == *rCmpList.GetObject(i);
1573 return bEq;
1576 /*************************************************************************
1578 |* XPolyPolygon::XPolyPolygon()
1580 |* Beschreibung POLY.SDW
1581 |* Ersterstellung CL 27.01.93
1582 |* Letzte Aenderung CL 27.01.93
1584 *************************************************************************/
1586 XPolyPolygon::XPolyPolygon( USHORT nInitSize, USHORT nResize )
1588 DBG_CTOR(XPolyPolygon,NULL);
1589 pImpXPolyPolygon = new ImpXPolyPolygon( nInitSize, nResize );
1593 /*************************************************************************
1595 |* XPolyPolygon::XPolyPolygon()
1597 |* Beschreibung POLY.SDW
1598 |* Ersterstellung CL 27.01.93
1599 |* Letzte Aenderung CL 27.01.93
1601 *************************************************************************/
1603 XPolyPolygon::XPolyPolygon( const XPolygon& rXPoly )
1605 DBG_CTOR(XPolyPolygon,NULL);
1606 pImpXPolyPolygon = new ImpXPolyPolygon;
1607 pImpXPolyPolygon->aXPolyList.Insert( new XPolygon( rXPoly ) );
1610 /*************************************************************************
1612 |* XPolyPolygon::XPolyPolygon()
1614 |* Beschreibung POLY.SDW
1615 |* Ersterstellung CL 27.01.93
1616 |* Letzte Aenderung CL 27.01.93
1618 *************************************************************************/
1620 XPolyPolygon::XPolyPolygon( const XPolyPolygon& rXPolyPoly )
1622 DBG_CTOR(XPolyPolygon,NULL);
1623 pImpXPolyPolygon = rXPolyPoly.pImpXPolyPolygon;
1624 pImpXPolyPolygon->nRefCount++;
1627 /*************************************************************************
1629 |* XPolyPolygon::XPolyPolygon()
1631 |* XPolyPolygon aus einen Standard-PolyPolygon erzeugen
1632 |* Ersterstellung 18.01.95 ESO
1633 |* Letzte Aenderung 18.01.95 ESO
1635 *************************************************************************/
1637 XPolyPolygon::XPolyPolygon( const PolyPolygon& rPolyPoly )
1639 DBG_CTOR(XPolyPolygon,NULL);
1640 pImpXPolyPolygon = new ImpXPolyPolygon;
1642 for (USHORT i = 0; i < rPolyPoly.Count(); i++)
1643 pImpXPolyPolygon->aXPolyList.Insert(
1644 new XPolygon(rPolyPoly.GetObject(i)) );
1647 /*************************************************************************
1649 |* XPolyPolygon::~XPolyPolygon()
1651 |* Beschreibung POLY.SDW
1652 |* Ersterstellung CL 27.01.93
1653 |* Letzte Aenderung CL 27.01.93
1655 *************************************************************************/
1657 XPolyPolygon::~XPolyPolygon()
1659 DBG_DTOR(XPolyPolygon,NULL);
1660 if( pImpXPolyPolygon->nRefCount > 1 )
1661 pImpXPolyPolygon->nRefCount--;
1662 else
1663 delete pImpXPolyPolygon;
1666 /*************************************************************************
1668 |* XPolygon::CheckReference()
1670 |* Referenzzaehler desImpXPolyPoly pruefen und ggf. von diesem abkoppeln
1671 |* Ersterstellung 18.01.95 ESO
1672 |* Letzte Aenderung 18.01.95 ESO
1674 *************************************************************************/
1676 void XPolyPolygon::CheckReference()
1678 if( pImpXPolyPolygon->nRefCount > 1 )
1680 pImpXPolyPolygon->nRefCount--;
1681 pImpXPolyPolygon = new ImpXPolyPolygon( *pImpXPolyPolygon );
1685 /*************************************************************************
1687 |* XPolyPolygon::Insert()
1689 |* Beschreibung POLY.SDW
1690 |* Ersterstellung CL 27.01.93
1691 |* Letzte Aenderung CL 27.01.93
1693 *************************************************************************/
1695 void XPolyPolygon::Insert( const XPolygon& rXPoly, USHORT nPos )
1697 CheckReference();
1698 XPolygon* pXPoly = new XPolygon( rXPoly );
1699 pImpXPolyPolygon->aXPolyList.Insert( pXPoly, nPos );
1702 /*************************************************************************
1704 |* XPolyPolygon::Insert()
1706 |* saemtliche XPolygone aus einem XPolyPolygon einfuegen
1707 |* Ersterstellung 18.01.95 ESO
1708 |* Letzte Aenderung 18.01.95 ESO
1710 *************************************************************************/
1712 void XPolyPolygon::Insert( const XPolyPolygon& rXPolyPoly, USHORT nPos )
1714 CheckReference();
1716 for (USHORT i = 0; i < rXPolyPoly.Count(); i++)
1718 XPolygon* pXPoly = new XPolygon(rXPolyPoly[i]);
1719 pImpXPolyPolygon->aXPolyList.Insert(pXPoly, nPos);
1720 if ( nPos != XPOLYPOLY_APPEND )
1721 nPos++;
1725 /*************************************************************************
1727 |* XPolyPolygon::Remove()
1729 |* Beschreibung POLY.SDW
1730 |* Ersterstellung CL 27.01.93
1731 |* Letzte Aenderung CL 27.01.93
1733 *************************************************************************/
1735 XPolygon XPolyPolygon::Remove( USHORT nPos )
1737 CheckReference();
1738 XPolygon* pTmpXPoly = pImpXPolyPolygon->aXPolyList.Remove( nPos );
1739 XPolygon aXPoly( *pTmpXPoly );
1740 delete pTmpXPoly;
1741 return aXPoly;
1745 /*************************************************************************
1747 |* XPolyPolygon::Replace()
1749 |* Beschreibung POLY.SDW
1750 |* Ersterstellung CL 27.01.93
1751 |* Letzte Aenderung CL 27.01.93
1753 *************************************************************************/
1755 XPolygon XPolyPolygon::Replace( const XPolygon& rXPoly, USHORT nPos )
1757 CheckReference();
1758 XPolygon* pXPoly = new XPolygon( rXPoly );
1759 XPolygon* pTmpXPoly = pImpXPolyPolygon->aXPolyList.Replace( pXPoly, nPos );
1760 XPolygon aXPoly( *pTmpXPoly );
1761 delete pTmpXPoly;
1762 return aXPoly;
1766 /*************************************************************************
1768 |* XPolyPolygon::GetObject()
1770 |* Beschreibung POLY.SDW
1771 |* Ersterstellung CL 27.01.93
1772 |* Letzte Aenderung CL 27.01.93
1774 *************************************************************************/
1776 const XPolygon& XPolyPolygon::GetObject( USHORT nPos ) const
1778 return *(pImpXPolyPolygon->aXPolyList.GetObject( nPos ));
1782 /*************************************************************************
1784 |* XPolyPolygon::Clear()
1786 |* Beschreibung POLY.SDW
1787 |* Ersterstellung CL 27.01.93
1788 |* Letzte Aenderung TH 17.10.94
1790 *************************************************************************/
1792 void XPolyPolygon::Clear()
1794 if ( pImpXPolyPolygon->nRefCount > 1 )
1796 pImpXPolyPolygon->nRefCount--;
1797 pImpXPolyPolygon = new ImpXPolyPolygon();
1799 else
1801 XPolygon* pXPoly = pImpXPolyPolygon->aXPolyList.First();
1802 while( pXPoly )
1804 delete pXPoly;
1805 pXPoly = pImpXPolyPolygon->aXPolyList.Next();
1807 pImpXPolyPolygon->aXPolyList.Clear();
1812 /*************************************************************************
1814 |* XPolyPolygon::Count()
1816 |* Beschreibung
1817 |* Ersterstellung CL 27.01.93
1818 |* Letzte Aenderung CL 27.01.93
1820 *************************************************************************/
1822 USHORT XPolyPolygon::Count() const
1824 return (USHORT)(pImpXPolyPolygon->aXPolyList.Count());
1828 /*************************************************************************
1830 |* XPolyPolygon::Move()
1832 |* Beschreibung POLY.SDW
1833 |* Ersterstellung TH 04.10.94
1834 |* Letzte Aenderung TH 04.10.94
1836 *************************************************************************/
1838 void XPolyPolygon::Move( long nHorzMove, long nVertMove )
1840 // Diese Abfrage sollte man fuer die DrawEngine durchfuehren
1841 if ( !nHorzMove && !nVertMove )
1842 return;
1844 // Referenzcounter beruecksichtigen
1845 CheckReference();
1847 // Punkte verschieben
1848 XPolygon* pXPoly = pImpXPolyPolygon->aXPolyList.First();
1849 while( pXPoly )
1851 pXPoly->Move( nHorzMove, nVertMove );
1852 pXPoly = pImpXPolyPolygon->aXPolyList.Next();
1856 /*************************************************************************
1858 |* XPolyPolygon::GetBoundRect()
1860 |* Beschreibung POLY.SDW
1861 |* Ersterstellung TH 04.10.94
1862 |* Letzte Aenderung TH 04.10.94
1864 *************************************************************************/
1866 Rectangle XPolyPolygon::GetBoundRect() const
1868 USHORT nXPoly = (USHORT)pImpXPolyPolygon->aXPolyList.Count();
1869 Rectangle aRect;
1871 for ( USHORT n = 0; n < nXPoly; n++ )
1873 const XPolygon* pXPoly = pImpXPolyPolygon->aXPolyList.GetObject( n );
1874 aRect.Union( pXPoly->GetBoundRect() );
1877 return aRect;
1881 /*************************************************************************
1883 |* XPolyPolygon::operator[]()
1885 |* Beschreibung POLY.SDW
1886 |* Ersterstellung TH 28.10.94
1887 |* Letzte Aenderung TH 28.10.94
1889 *************************************************************************/
1891 XPolygon& XPolyPolygon::operator[]( USHORT nPos )
1893 CheckReference();
1894 return *(pImpXPolyPolygon->aXPolyList.GetObject( nPos ));
1897 /*************************************************************************
1899 |* XPolyPolygon::operator=()
1901 |* Beschreibung POLY.SDW
1902 |* Ersterstellung CL 27.01.93
1903 |* Letzte Aenderung CL 27.01.93
1905 *************************************************************************/
1907 XPolyPolygon& XPolyPolygon::operator=( const XPolyPolygon& rXPolyPoly )
1909 rXPolyPoly.pImpXPolyPolygon->nRefCount++;
1911 if( pImpXPolyPolygon->nRefCount > 1 )
1912 pImpXPolyPolygon->nRefCount--;
1913 else
1914 delete pImpXPolyPolygon;
1916 pImpXPolyPolygon = rXPolyPoly.pImpXPolyPolygon;
1917 return *this;
1921 /*************************************************************************
1923 |* XPolyPolygon::operator==()
1925 |* Beschreibung POLY.SDW
1926 |* Ersterstellung CL 27.01.93
1927 |* Letzte Aenderung Joe 27.01.93
1929 *************************************************************************/
1931 BOOL XPolyPolygon::operator==( const XPolyPolygon& rXPolyPoly ) const
1933 if (pImpXPolyPolygon==rXPolyPoly.pImpXPolyPolygon) return TRUE;
1934 return *pImpXPolyPolygon == *rXPolyPoly.pImpXPolyPolygon;
1938 /*************************************************************************
1940 |* XPolyPolygon::operator!=()
1942 |* Beschreibung POLY.SDW
1943 |* Ersterstellung CL 27.01.93
1944 |* Letzte Aenderung Joe 27.01.93
1946 *************************************************************************/
1948 BOOL XPolyPolygon::operator!=( const XPolyPolygon& rXPolyPoly ) const
1950 if (pImpXPolyPolygon==rXPolyPoly.pImpXPolyPolygon) return FALSE;
1951 return *pImpXPolyPolygon != *rXPolyPoly.pImpXPolyPolygon;
1954 /*************************************************************************
1956 |* XPolyPolygon::Translate()
1958 |* Alle Polygone auf den uebergebenen Punkt verschieben
1959 |* Ersterstellung ESO 25.01.95
1960 |* Letzte Aenderung ESO 25.01.95
1962 *************************************************************************/
1964 void XPolyPolygon::Translate(const Point& rTrans)
1966 CheckReference();
1968 for (USHORT i = 0; i < Count(); i++)
1969 pImpXPolyPolygon->aXPolyList.GetObject(i)->Translate(rTrans);
1972 /*************************************************************************
1974 |* XPolyPolygon::Rotate()
1976 |* Alle Polygone um den Punkt rCenter drehen, Sinus und Cosinus
1977 |* muessen uebergeben werden
1978 |* Ersterstellung ESO 25.01.95
1979 |* Letzte Aenderung ESO 25.01.95
1981 *************************************************************************/
1983 void XPolyPolygon::Rotate(const Point& rCenter, double fSin, double fCos)
1985 CheckReference();
1987 for (USHORT i = 0; i < Count(); i++)
1988 pImpXPolyPolygon->aXPolyList.GetObject(i)->Rotate(rCenter, fSin, fCos);
1991 /*************************************************************************
1993 |* Bestimme den linken, unteren Punkt des Polygons und richte das
1994 |* Polygon so aus, dass dieser Punkt auf dem Index 0 liegt
1996 \************************************************************************/
1998 void XPolyPolygon::Rotate20()
2000 CheckReference();
2002 for (USHORT i = 0; i < Count(); i++)
2003 pImpXPolyPolygon->aXPolyList.GetObject(i)->Rotate20();
2006 /*************************************************************************
2008 |* XPolyPolygon::Rotate()
2010 |* Alle Poylgone um den Punkt rCenter mit dem Winkel nAngle drehen
2011 |* Winkel in 10tel Grad, Wertebereich 0 - 3600
2012 |* Ersterstellung ESO 25.01.95
2013 |* Letzte Aenderung ESO 25.01.95
2015 *************************************************************************/
2017 void XPolyPolygon::Rotate(const Point& rCenter, USHORT nAngle)
2019 nAngle %= 3600;
2021 if ( nAngle != 0 )
2023 double fAngle = F_PI * nAngle / 1800;
2024 double fSin = sin(fAngle);
2025 double fCos = cos(fAngle);
2026 Rotate(rCenter, fSin, fCos);
2030 /*************************************************************************
2032 |* XPolyPolygon::Scale()
2034 |* Alle Polygone in X- und/oder Y-Richtung skalieren
2035 |* Ersterstellung ESO 01.02.95
2036 |* Letzte Aenderung ESO 01.02.95
2038 *************************************************************************/
2040 void XPolyPolygon::Scale(double fSx, double fSy)
2042 CheckReference();
2044 for (USHORT i = 0; i < Count(); i++)
2045 pImpXPolyPolygon->aXPolyList.GetObject(i)->Scale(fSx, fSy);
2048 /*************************************************************************
2050 |* XPolyPolygon::SlantX()
2052 |* Alle Polygone in X-Richtung um einen beliebigen Winkel kippen,
2053 |* bezogen auf eine Referenz-Y-Koordinate
2054 |* Ersterstellung ESO 01.02.95
2055 |* Letzte Aenderung ESO 01.02.95
2057 *************************************************************************/
2059 void XPolyPolygon::SlantX(long nYRef, double fSin, double fCos)
2061 CheckReference();
2063 for (USHORT i = 0; i < Count(); i++)
2064 pImpXPolyPolygon->aXPolyList.GetObject(i)->SlantX(nYRef, fSin, fCos);
2067 /*************************************************************************
2069 |* XPolyPolygon::SlantY()
2071 |* Alle Polygone in Y-Richtung um einen beliebigen Winkel kippen,
2072 |* bezogen auf eine Referenz-X-Koordinate
2073 |* Ersterstellung ESO 01.02.95
2074 |* Letzte Aenderung ESO 01.02.95
2076 *************************************************************************/
2078 void XPolyPolygon::SlantY(long nXRef, double fSin, double fCos)
2080 CheckReference();
2082 for (USHORT i = 0; i < Count(); i++)
2083 pImpXPolyPolygon->aXPolyList.GetObject(i)->SlantY(nXRef, fSin, fCos);
2086 /*************************************************************************
2088 |* XPolygon::Distort()
2090 |* XPolygon verzerren, indem die Koordinaten relativ zu einem
2091 |* Referenzrechteck in ein beliebiges Viereck skaliert werden
2092 |* Zuordnung der Viereck-Punkte im Polygon zum Referenzrechteck:
2093 |* 0: links oben 0----1
2094 |* 1: rechts oben | |
2095 |* 2: rechts unten 3----2
2096 |* 3: links unten
2097 |* Ersterstellung ESO 07.07.95
2098 |* Letzte Aenderung ESO 07.07.95
2100 *************************************************************************/
2102 void XPolyPolygon::Distort(const Rectangle& rRefRect,
2103 const XPolygon& rDistortedRect)
2105 CheckReference();
2107 for (USHORT i = 0; i < Count(); i++)
2108 pImpXPolyPolygon->aXPolyList.GetObject(i)->Distort(rRefRect,
2109 rDistortedRect);
2112 basegfx::B2DPolyPolygon XPolyPolygon::getB2DPolyPolygon() const
2114 basegfx::B2DPolyPolygon aRetval;
2116 for(sal_uInt16 a(0L); a < Count(); a++)
2118 const XPolygon& rPoly = (*this)[a];
2119 aRetval.append(rPoly.getB2DPolygon());
2122 return aRetval;
2125 XPolyPolygon::XPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon)
2127 DBG_CTOR(XPolyPolygon,NULL);
2128 pImpXPolyPolygon = new ImpXPolyPolygon( 16, 16 );
2130 for(sal_uInt32 a(0L); a < rPolyPolygon.count(); a++)
2132 basegfx::B2DPolygon aCandidate = rPolyPolygon.getB2DPolygon(a);
2133 XPolygon aNewPoly(aCandidate);
2134 Insert(aNewPoly);
2138 // eof