1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <osl/endian.h>
21 #include <tools/stream.hxx>
22 #include <tools/debug.hxx>
23 #include <tools/poly.hxx>
24 #include <tools/helpers.hxx>
25 #include <tools/gen.hxx>
27 #include <svx/xpoly.hxx>
28 #include "xpolyimp.hxx"
29 #include <basegfx/polygon/b2dpolygon.hxx>
30 #include <basegfx/point/b2dpoint.hxx>
31 #include <basegfx/vector/b2dvector.hxx>
32 #include <basegfx/polygon/b2dpolygontools.hxx>
33 #include <basegfx/range/b2drange.hxx>
34 #include <basegfx/numeric/ftools.hxx>
37 DBG_NAME(XPolyPolygon
);
39 /*************************************************************************
41 |* ImpXPolygon::ImpXPolygon()
43 *************************************************************************/
45 ImpXPolygon::ImpXPolygon( sal_uInt16 nInitSize
, sal_uInt16 _nResize
)
49 bDeleteOldPoints
= sal_False
;
58 /*************************************************************************
60 |* ImpXPolygon::ImpXPolygon()
62 *************************************************************************/
64 ImpXPolygon::ImpXPolygon( const ImpXPolygon
& rImpXPoly
)
66 ( (ImpXPolygon
&) rImpXPoly
).CheckPointDelete();
70 bDeleteOldPoints
= sal_False
;
72 ImpXPolygon::nResize
= rImpXPoly
.nResize
;
76 Resize( rImpXPoly
.nSize
);
79 nPoints
= rImpXPoly
.nPoints
;
80 memcpy( pPointAry
, rImpXPoly
.pPointAry
, nSize
*sizeof( Point
) );
81 memcpy( pFlagAry
, rImpXPoly
.pFlagAry
, nSize
);
84 /*************************************************************************
86 |* ImpXPolygon::~ImpXPolygon()
88 *************************************************************************/
90 ImpXPolygon::~ImpXPolygon()
92 delete[] (char*) pPointAry
;
94 if ( bDeleteOldPoints
)
95 delete[] (char*) pOldPointAry
;
98 /*************************************************************************
100 |* ImpXPolygon::operator==()
102 *************************************************************************/
105 bool ImpXPolygon::operator==(const ImpXPolygon
& rImpXPoly
) const
107 return nPoints
==rImpXPoly
.nPoints
&&
109 (memcmp(pPointAry
,rImpXPoly
.pPointAry
,nPoints
*sizeof(Point
))==0 &&
110 memcmp(pFlagAry
,rImpXPoly
.pFlagAry
,nPoints
)==0));
113 /*************************************************************************
115 |* ImpXPolygon::Resize()
117 |* !!! Polygongroesse aendern - wenn bDeletePoints sal_False, dann den
118 |* Point-Array nicht loeschen, sondern in pOldPointAry sichern und
119 |* das Flag bDeleteOldPoints setzen. Beim naechsten Zugriff wird
120 |* das Array dann geloescht.
121 |* Damit wird verhindert, dass bei XPoly[n] = XPoly[0] durch ein
122 |* Resize der fuer den rechten Ausdruck verwendete Point-Array
123 |* vorzeitig geloescht wird.
125 *************************************************************************/
127 void ImpXPolygon::Resize( sal_uInt16 nNewSize
, sal_Bool bDeletePoints
)
129 if( nNewSize
== nSize
)
132 sal_uInt8
* pOldFlagAry
= pFlagAry
;
133 sal_uInt16 nOldSize
= nSize
;
136 pOldPointAry
= pPointAry
;
138 // Neue Groesse auf vielfaches von nResize runden, sofern Objekt
139 // nicht neu angelegt wurde (nSize != 0)
140 if ( nSize
!= 0 && nNewSize
> nSize
)
142 DBG_ASSERT(nResize
, "Resize-Versuch trotz nResize = 0 !");
143 nNewSize
= nSize
+ ((nNewSize
-nSize
-1) / nResize
+ 1) * nResize
;
145 // Punkt Array erzeugen
147 pPointAry
= (Point
*)new char[ nSize
*sizeof( Point
) ];
148 memset( pPointAry
, 0, nSize
*sizeof( Point
) );
150 // Flag Array erzeugen
151 pFlagAry
= new sal_uInt8
[ nSize
];
152 memset( pFlagAry
, 0, nSize
);
154 // Eventuell umkopieren
157 if( nOldSize
< nSize
)
159 memcpy( pPointAry
, pOldPointAry
, nOldSize
*sizeof( Point
) );
160 memcpy( pFlagAry
, pOldFlagAry
, nOldSize
);
164 memcpy( pPointAry
, pOldPointAry
, nSize
*sizeof( Point
) );
165 memcpy( pFlagAry
, pOldFlagAry
, nSize
);
167 // Anzahl der gueltigen Punkte anpassen
168 if( nPoints
> nSize
)
171 if ( bDeletePoints
) delete[] (char*) pOldPointAry
;
172 else bDeleteOldPoints
= sal_True
;
173 delete[] pOldFlagAry
;
178 /*************************************************************************
180 |* ImpXPolygon::InsertSpace()
182 *************************************************************************/
184 void ImpXPolygon::InsertSpace( sal_uInt16 nPos
, sal_uInt16 nCount
)
188 if ( nPos
> nPoints
)
191 // Wenn Polygon zu klein dann groesser machen
192 if( (nPoints
+ nCount
) > nSize
)
193 Resize( nPoints
+ nCount
);
195 // Wenn nicht hinter dem letzten Punkt eingefuegt wurde,
196 // den Rest nach hinten schieben
199 sal_uInt16 nMove
= nPoints
- nPos
;
200 memmove( &pPointAry
[nPos
+nCount
], &pPointAry
[nPos
],
201 nMove
* sizeof(Point
) );
202 memmove( &pFlagAry
[nPos
+nCount
], &pFlagAry
[nPos
], nMove
);
204 memset( &pPointAry
[nPos
], 0, nCount
* sizeof( Point
) );
205 memset( &pFlagAry
[nPos
], 0, nCount
);
207 nPoints
= nPoints
+ nCount
;
211 /*************************************************************************
213 |* ImpXPolygon::Remove()
215 *************************************************************************/
217 void ImpXPolygon::Remove( sal_uInt16 nPos
, sal_uInt16 nCount
)
221 if( (nPos
+ nCount
) <= nPoints
)
223 sal_uInt16 nMove
= nPoints
- nPos
- nCount
;
227 memmove( &pPointAry
[nPos
], &pPointAry
[nPos
+nCount
],
228 nMove
* sizeof(Point
) );
229 memmove( &pFlagAry
[nPos
], &pFlagAry
[nPos
+nCount
], nMove
);
231 memset( &pPointAry
[nPoints
- nCount
], 0, nCount
* sizeof( Point
) );
232 memset( &pFlagAry
[nPoints
- nCount
], 0, nCount
);
233 nPoints
= nPoints
- nCount
;
238 /*************************************************************************
240 |* XPolygon::XPolygon()
242 *************************************************************************/
244 XPolygon::XPolygon( sal_uInt16 nSize
, sal_uInt16 nResize
)
246 DBG_CTOR(XPolygon
,NULL
);
247 pImpXPolygon
= new ImpXPolygon( nSize
, nResize
);
250 /*************************************************************************
252 |* XPolygon::XPolygon()
254 *************************************************************************/
256 XPolygon::XPolygon( const XPolygon
& rXPoly
)
258 DBG_CTOR(XPolygon
,NULL
);
259 pImpXPolygon
= rXPoly
.pImpXPolygon
;
260 pImpXPolygon
->nRefCount
++;
263 /*************************************************************************
265 |* XPolygon::XPolygon()
267 |* Rechteck (auch mit abgerundeten Ecken) als Bezierpolygon erzeugen
269 *************************************************************************/
271 XPolygon::XPolygon(const Rectangle
& rRect
, long nRx
, long nRy
)
273 DBG_CTOR(XPolygon
,NULL
);
274 pImpXPolygon
= new ImpXPolygon(17);
275 long nWh
= (rRect
.GetWidth() - 1) / 2;
276 long nHh
= (rRect
.GetHeight() - 1) / 2;
278 if ( nRx
> nWh
) nRx
= nWh
;
279 if ( nRy
> nHh
) nRy
= nHh
;
281 // Rx negativ, damit Umlauf im Uhrzeigersinn erfolgt
284 // Faktor fuer Kontrollpunkte der Bezierkurven: 8/3 * (sin(45g) - 0.5)
285 long nXHdl
= (long)(0.552284749 * nRx
);
286 long nYHdl
= (long)(0.552284749 * nRy
);
293 for (sal_uInt16 nQuad
= 0; nQuad
< 4; nQuad
++)
297 case 0: aCenter
= rRect
.TopLeft();
301 case 1: aCenter
= rRect
.TopRight();
305 case 2: aCenter
= rRect
.BottomRight();
309 case 3: aCenter
= rRect
.BottomLeft();
314 GenBezArc(aCenter
, nRx
, nRy
, nXHdl
, nYHdl
, 0, 900, nQuad
, nPos
);
315 pImpXPolygon
->pFlagAry
[nPos
] = (sal_uInt8
) XPOLY_SMOOTH
;
316 pImpXPolygon
->pFlagAry
[nPos
+3] = (sal_uInt8
) XPOLY_SMOOTH
;
322 pImpXPolygon
->pPointAry
[nPos
++] = rRect
.TopLeft();
323 pImpXPolygon
->pPointAry
[nPos
++] = rRect
.TopRight();
324 pImpXPolygon
->pPointAry
[nPos
++] = rRect
.BottomRight();
325 pImpXPolygon
->pPointAry
[nPos
++] = rRect
.BottomLeft();
327 pImpXPolygon
->pPointAry
[nPos
] = pImpXPolygon
->pPointAry
[0];
328 pImpXPolygon
->nPoints
= nPos
+ 1;
331 /*************************************************************************
333 |* XPolygon::XPolygon()
335 |* Ellipsen(bogen) als Bezierpolygon erzeugen
337 *************************************************************************/
339 XPolygon::XPolygon(const Point
& rCenter
, long nRx
, long nRy
,
340 sal_uInt16 nStartAngle
, sal_uInt16 nEndAngle
, sal_Bool bClose
)
342 DBG_CTOR(XPolygon
,NULL
);
343 pImpXPolygon
= new ImpXPolygon(17);
346 if ( nEndAngle
> 3600 ) nEndAngle
%= 3600;
347 bool bFull
= (nStartAngle
== 0 && nEndAngle
== 3600);
349 // Faktor fuer Kontrollpunkte der Bezierkurven: 8/3 * (sin(45g) - 0.5)
350 long nXHdl
= (long)(0.552284749 * nRx
);
351 long nYHdl
= (long)(0.552284749 * nRy
);
353 sal_Bool bLoopEnd
= sal_False
;
358 sal_uInt16 nQuad
= nStartAngle
/ 900;
359 if ( nQuad
== 4 ) nQuad
= 0;
360 bLoopEnd
= CheckAngles(nStartAngle
, nEndAngle
, nA1
, nA2
);
361 GenBezArc(rCenter
, nRx
, nRy
, nXHdl
, nYHdl
, nA1
, nA2
, nQuad
, nPos
);
364 pImpXPolygon
->pFlagAry
[nPos
] = (sal_uInt8
) XPOLY_SMOOTH
;
366 } while ( !bLoopEnd
);
368 // Wenn kein Vollkreis, dann ggf. Enden mit Mittelpunkt verbinden
369 if ( !bFull
&& bClose
)
370 pImpXPolygon
->pPointAry
[++nPos
] = rCenter
;
374 pImpXPolygon
->pFlagAry
[0 ] = (sal_uInt8
) XPOLY_SMOOTH
;
375 pImpXPolygon
->pFlagAry
[nPos
] = (sal_uInt8
) XPOLY_SMOOTH
;
377 pImpXPolygon
->nPoints
= nPos
+ 1;
380 /*************************************************************************
382 |* XPolygon::~XPolygon()
384 *************************************************************************/
386 XPolygon::~XPolygon()
388 DBG_DTOR(XPolygon
,NULL
);
389 if( pImpXPolygon
->nRefCount
> 1 )
390 pImpXPolygon
->nRefCount
--;
395 /*************************************************************************
397 |* XPolygon::CheckReference()
399 |* Referenzzaehler desImpXPoly pruefen und ggf. von diesem abkoppeln
401 *************************************************************************/
403 void XPolygon::CheckReference()
405 if( pImpXPolygon
->nRefCount
> 1 )
407 pImpXPolygon
->nRefCount
--;
408 pImpXPolygon
= new ImpXPolygon( *pImpXPolygon
);
412 /*************************************************************************
414 |* XPolygon::SetPointCount()
416 *************************************************************************/
418 void XPolygon::SetPointCount( sal_uInt16 nPoints
)
420 pImpXPolygon
->CheckPointDelete();
423 if( pImpXPolygon
->nSize
< nPoints
)
424 pImpXPolygon
->Resize( nPoints
);
426 if ( nPoints
< pImpXPolygon
->nPoints
)
428 sal_uInt16 nSize
= pImpXPolygon
->nPoints
- nPoints
;
429 memset( &pImpXPolygon
->pPointAry
[nPoints
], 0, nSize
* sizeof( Point
) );
430 memset( &pImpXPolygon
->pFlagAry
[nPoints
], 0, nSize
);
432 pImpXPolygon
->nPoints
= nPoints
;
435 /*************************************************************************
437 |* XPolygon::GetPointCount()
439 *************************************************************************/
441 sal_uInt16
XPolygon::GetPointCount() const
443 pImpXPolygon
->CheckPointDelete();
444 return pImpXPolygon
->nPoints
;
447 /*************************************************************************
449 |* XPolygon::Insert()
451 *************************************************************************/
453 void XPolygon::Insert( sal_uInt16 nPos
, const Point
& rPt
, XPolyFlags eFlags
)
456 if (nPos
>pImpXPolygon
->nPoints
) nPos
=pImpXPolygon
->nPoints
;
457 pImpXPolygon
->InsertSpace( nPos
, 1 );
458 pImpXPolygon
->pPointAry
[nPos
] = rPt
;
459 pImpXPolygon
->pFlagAry
[nPos
] = (sal_uInt8
)eFlags
;
462 /*************************************************************************
464 |* XPolygon::Insert()
466 *************************************************************************/
468 void XPolygon::Insert( sal_uInt16 nPos
, const XPolygon
& rXPoly
)
471 if (nPos
>pImpXPolygon
->nPoints
) nPos
=pImpXPolygon
->nPoints
;
473 sal_uInt16 nPoints
= rXPoly
.GetPointCount();
475 pImpXPolygon
->InsertSpace( nPos
, nPoints
);
477 memcpy( &(pImpXPolygon
->pPointAry
[nPos
]),
478 rXPoly
.pImpXPolygon
->pPointAry
,
479 nPoints
*sizeof( Point
) );
480 memcpy( &(pImpXPolygon
->pFlagAry
[nPos
]),
481 rXPoly
.pImpXPolygon
->pFlagAry
,
485 /*************************************************************************
487 |* XPolygon::Remove()
489 *************************************************************************/
491 void XPolygon::Remove( sal_uInt16 nPos
, sal_uInt16 nCount
)
494 pImpXPolygon
->Remove( nPos
, nCount
);
497 /*************************************************************************
501 *************************************************************************/
503 void XPolygon::Move( long nHorzMove
, long nVertMove
)
505 if ( !nHorzMove
&& !nVertMove
)
510 // Punkte verschieben
511 sal_uInt16 nCount
= pImpXPolygon
->nPoints
;
512 for ( sal_uInt16 i
= 0; i
< nCount
; i
++ )
514 Point
* pPt
= &(pImpXPolygon
->pPointAry
[i
]);
515 pPt
->X() += nHorzMove
;
516 pPt
->Y() += nVertMove
;
520 /*************************************************************************
522 |* XPolygon::GetBoundRect()
524 *************************************************************************/
526 Rectangle
XPolygon::GetBoundRect() const
528 pImpXPolygon
->CheckPointDelete();
531 if(pImpXPolygon
->nPoints
)
534 // For historical reasons the control points are not part of the
535 // BoundRect. This makes it necessary to subdivide the polygon to
536 // get a relatively correct BoundRect. Numerically, this is not
537 // correct and never was.
539 const basegfx::B2DRange
aPolygonRange(basegfx::tools::getRange(getB2DPolygon()));
541 FRound(aPolygonRange
.getMinX()), FRound(aPolygonRange
.getMinY()),
542 FRound(aPolygonRange
.getMaxX()), FRound(aPolygonRange
.getMaxY()));
548 /*************************************************************************
550 |* XPolygon::operator[]()
552 *************************************************************************/
554 const Point
& XPolygon::operator[]( sal_uInt16 nPos
) const
556 DBG_ASSERT(nPos
< pImpXPolygon
->nPoints
, "Ungueltiger Index bei const-Arrayzugriff auf XPolygon");
558 pImpXPolygon
->CheckPointDelete();
559 return pImpXPolygon
->pPointAry
[nPos
];
562 /*************************************************************************
564 |* XPolygon::operator[]()
566 *************************************************************************/
568 Point
& XPolygon::operator[]( sal_uInt16 nPos
)
570 pImpXPolygon
->CheckPointDelete();
573 if( nPos
>= pImpXPolygon
->nSize
)
575 DBG_ASSERT(pImpXPolygon
->nResize
, "Ungueltiger Index bei Arrayzugriff auf XPolygon");
576 pImpXPolygon
->Resize(nPos
+ 1, sal_False
);
578 if( nPos
>= pImpXPolygon
->nPoints
)
579 pImpXPolygon
->nPoints
= nPos
+ 1;
581 return pImpXPolygon
->pPointAry
[nPos
];
584 /*************************************************************************
586 |* XPolygon::operator=()
588 |* Beschreibung Zuweisungsoperator
590 *************************************************************************/
592 XPolygon
& XPolygon::operator=( const XPolygon
& rXPoly
)
594 pImpXPolygon
->CheckPointDelete();
596 rXPoly
.pImpXPolygon
->nRefCount
++;
598 if( pImpXPolygon
->nRefCount
> 1 )
599 pImpXPolygon
->nRefCount
--;
603 pImpXPolygon
= rXPoly
.pImpXPolygon
;
607 /*************************************************************************
609 |* XPolygon::operator==()
611 |* Beschreibung Gleichheitsoperator
613 *************************************************************************/
615 sal_Bool
XPolygon::operator==( const XPolygon
& rXPoly
) const
617 pImpXPolygon
->CheckPointDelete();
618 if (rXPoly
.pImpXPolygon
==pImpXPolygon
) return sal_True
;
619 return *rXPoly
.pImpXPolygon
== *pImpXPolygon
;
622 /*************************************************************************
624 |* XPolygon::operator!=()
626 |* Beschreibung Ungleichheitsoperator
628 *************************************************************************/
630 sal_Bool
XPolygon::operator!=( const XPolygon
& rXPoly
) const
632 pImpXPolygon
->CheckPointDelete();
633 if (rXPoly
.pImpXPolygon
==pImpXPolygon
) return sal_False
;
634 return *rXPoly
.pImpXPolygon
!= *pImpXPolygon
;
637 /*************************************************************************
639 |* XPolygon::GetFlags()
641 |* Flags fuer den Punkt an der Position nPos zurueckgeben
643 *************************************************************************/
645 XPolyFlags
XPolygon::GetFlags( sal_uInt16 nPos
) const
647 pImpXPolygon
->CheckPointDelete();
648 return (XPolyFlags
) pImpXPolygon
->pFlagAry
[nPos
];
651 /*************************************************************************
653 |* XPolygon::SetFlags()
655 |* Flags fuer den Punkt an der Position nPos setzen
657 *************************************************************************/
659 void XPolygon::SetFlags( sal_uInt16 nPos
, XPolyFlags eFlags
)
661 pImpXPolygon
->CheckPointDelete();
663 pImpXPolygon
->pFlagAry
[nPos
] = (sal_uInt8
) eFlags
;
666 /*************************************************************************
668 |* XPolygon::IsControl()
670 |* Kurzform zur Abfrage des CONTROL-Flags
672 *************************************************************************/
674 sal_Bool
XPolygon::IsControl(sal_uInt16 nPos
) const
676 return ( (XPolyFlags
) pImpXPolygon
->pFlagAry
[nPos
] == XPOLY_CONTROL
);
679 /*************************************************************************
681 |* XPolygon::IsSmooth()
683 |* Kurzform zur Abfrage von SMOOTH- und SYMMTR-Flag
685 *************************************************************************/
687 sal_Bool
XPolygon::IsSmooth(sal_uInt16 nPos
) const
689 XPolyFlags eFlag
= (XPolyFlags
) pImpXPolygon
->pFlagAry
[nPos
];
690 return ( eFlag
== XPOLY_SMOOTH
|| eFlag
== XPOLY_SYMMTR
);
693 /*************************************************************************
695 |* XPolygon::CalcDistance()
697 |* Abstand zwischen zwei Punkten berechnen
699 *************************************************************************/
701 double XPolygon::CalcDistance(sal_uInt16 nP1
, sal_uInt16 nP2
)
703 const Point
& rP1
= pImpXPolygon
->pPointAry
[nP1
];
704 const Point
& rP2
= pImpXPolygon
->pPointAry
[nP2
];
705 double fDx
= rP2
.X() - rP1
.X();
706 double fDy
= rP2
.Y() - rP1
.Y();
707 return sqrt(fDx
* fDx
+ fDy
* fDy
);
710 /*************************************************************************
712 |* XPolygon::SubdivideBezier()
714 |* Bezierkurve unterteilen
716 *************************************************************************/
718 void XPolygon::SubdivideBezier(sal_uInt16 nPos
, sal_Bool bCalcFirst
, double fT
)
720 Point
* pPoints
= pImpXPolygon
->pPointAry
;
721 double fT2
= fT
* fT
;
722 double fT3
= fT
* fT2
;
723 double fU
= 1.0 - fT
;
724 double fU2
= fU
* fU
;
725 double fU3
= fU
* fU2
;
726 sal_uInt16 nIdx
= nPos
;
727 short nPosInc
, nIdxInc
;
740 pPoints
[nPos
].X() = (long) (fU3
* pPoints
[nIdx
].X() +
741 fT
* fU2
* pPoints
[nIdx
+1].X() * 3 +
742 fT2
* fU
* pPoints
[nIdx
+2].X() * 3 +
743 fT3
* pPoints
[nIdx
+3].X());
744 pPoints
[nPos
].Y() = (long) (fU3
* pPoints
[nIdx
].Y() +
745 fT
* fU2
* pPoints
[nIdx
+1].Y() * 3 +
746 fT2
* fU
* pPoints
[nIdx
+2].Y() * 3 +
747 fT3
* pPoints
[nIdx
+3].Y());
748 nPos
= nPos
+ nPosInc
;
749 nIdx
= nIdx
+ nIdxInc
;
750 pPoints
[nPos
].X() = (long) (fU2
* pPoints
[nIdx
].X() +
751 fT
* fU
* pPoints
[nIdx
+1].X() * 2 +
752 fT2
* pPoints
[nIdx
+2].X());
753 pPoints
[nPos
].Y() = (long) (fU2
* pPoints
[nIdx
].Y() +
754 fT
* fU
* pPoints
[nIdx
+1].Y() * 2 +
755 fT2
* pPoints
[nIdx
+2].Y());
756 nPos
= nPos
+ nPosInc
;
757 nIdx
= nIdx
+ nIdxInc
;
758 pPoints
[nPos
].X() = (long) (fU
* pPoints
[nIdx
].X() +
759 fT
* pPoints
[nIdx
+1].X());
760 pPoints
[nPos
].Y() = (long) (fU
* pPoints
[nIdx
].Y() +
761 fT
* pPoints
[nIdx
+1].Y());
764 /************************************************************************/
766 void XPolygon::GenBezArc(const Point
& rCenter
, long nRx
, long nRy
,
767 long nXHdl
, long nYHdl
, sal_uInt16 nStart
, sal_uInt16 nEnd
,
768 sal_uInt16 nQuad
, sal_uInt16 nFirst
)
770 Point
* pPoints
= pImpXPolygon
->pPointAry
;
771 pPoints
[nFirst
] = rCenter
;
772 pPoints
[nFirst
+3] = rCenter
;
774 if ( nQuad
== 1 || nQuad
== 2 )
776 nRx
= -nRx
; nXHdl
= -nXHdl
;
778 if ( nQuad
== 0 || nQuad
== 1 )
780 nRy
= -nRy
; nYHdl
= -nYHdl
;
783 if ( nQuad
== 0 || nQuad
== 2 )
785 pPoints
[nFirst
].X() += nRx
; pPoints
[nFirst
+3].Y() += nRy
;
789 pPoints
[nFirst
].Y() += nRy
; pPoints
[nFirst
+3].X() += nRx
;
791 pPoints
[nFirst
+1] = pPoints
[nFirst
];
792 pPoints
[nFirst
+2] = pPoints
[nFirst
+3];
794 if ( nQuad
== 0 || nQuad
== 2 )
796 pPoints
[nFirst
+1].Y() += nYHdl
; pPoints
[nFirst
+2].X() += nXHdl
;
800 pPoints
[nFirst
+1].X() += nXHdl
; pPoints
[nFirst
+2].Y() += nYHdl
;
803 SubdivideBezier(nFirst
, sal_False
, (double)nStart
/ 900);
805 SubdivideBezier(nFirst
, sal_True
, (double)(nEnd
-nStart
) / (900-nStart
));
806 SetFlags(nFirst
+1, XPOLY_CONTROL
);
807 SetFlags(nFirst
+2, XPOLY_CONTROL
);
810 /************************************************************************/
812 sal_Bool
XPolygon::CheckAngles(sal_uInt16
& nStart
, sal_uInt16 nEnd
, sal_uInt16
& nA1
, sal_uInt16
& nA2
)
814 if ( nStart
== 3600 ) nStart
= 0;
815 if ( nEnd
== 0 ) nEnd
= 3600;
816 sal_uInt16 nStPrev
= nStart
;
817 sal_uInt16 nMax
= (nStart
/ 900 + 1) * 900;
818 sal_uInt16 nMin
= nMax
- 900;
820 if ( nEnd
>= nMax
|| nEnd
<= nStart
) nA2
= 900;
821 else nA2
= nEnd
- nMin
;
825 // sal_True zurueck, falls letztes Segment berechnet wurde
826 return (nStPrev
< nEnd
&& nStart
>= nEnd
);
829 /*************************************************************************
831 |* XPolygon::CalcSmoothJoin()
833 |* glatten Uebergang zu einer Bezierkurve berechnen, indem der
834 |* entsprechende Punkt auf die Verbindungslinie von zwei anderen
835 |* Punkten projiziert wird
836 |* Center = End- bzw. Anfangspunkt der Bezierkurve
837 |* Drag = der bewegte Punkt, der die Verschiebung von Pnt vorgibt
838 |* Pnt = der zu modifizierende Punkt
839 |* Wenn Center am Anfang bzw. Ende des Polygons liegt, wird Pnt
840 |* auf die entgegengesetzte Seite verlegt
842 \************************************************************************/
844 void XPolygon::CalcSmoothJoin(sal_uInt16 nCenter
, sal_uInt16 nDrag
, sal_uInt16 nPnt
)
848 // sal_uInt16 nMaxPnt = pImpXPolygon->nPoints - 1;
850 // if ( nCenter == nMaxPnt ) nPnt = 1;
851 // else if ( nCenter == 0 ) nPnt = nMaxPnt - 1;
853 // Wenn nPnt kein Control-Punkt, d.h. nicht verschiebbar, dann
854 // statt dessen nDrag auf der Achse nCenter-nPnt verschieben
855 if ( !IsControl(nPnt
) )
857 sal_uInt16 nTmp
= nDrag
;
861 Point
* pPoints
= pImpXPolygon
->pPointAry
;
862 Point aDiff
= pPoints
[nDrag
] - pPoints
[nCenter
];
863 double fDiv
= CalcDistance(nCenter
, nDrag
);
867 double fRatio
= CalcDistance(nCenter
, nPnt
) / fDiv
;
868 // bei SMOOTH bisherige Laenge beibehalten
869 if ( GetFlags(nCenter
) == XPOLY_SMOOTH
|| !IsControl(nDrag
) )
871 aDiff
.X() = (long) (fRatio
* aDiff
.X());
872 aDiff
.Y() = (long) (fRatio
* aDiff
.Y());
874 pPoints
[nPnt
] = pPoints
[nCenter
] - aDiff
;
878 /*************************************************************************
880 |* XPolygon::CalcTangent()
882 |* Tangente fuer den Uebergang zwischen zwei Bezierkurven berechnen
883 |* Center = End- bzw. Anfangspunkt der Bezierkurven
884 |* Prev = vorheriger Zugpunkt
885 |* Next = naechster Zugpunkt
887 \************************************************************************/
889 void XPolygon::CalcTangent(sal_uInt16 nCenter
, sal_uInt16 nPrev
, sal_uInt16 nNext
)
893 double fAbsLen
= CalcDistance(nNext
, nPrev
);
897 const Point
& rCenter
= pImpXPolygon
->pPointAry
[nCenter
];
898 Point
& rNext
= pImpXPolygon
->pPointAry
[nNext
];
899 Point
& rPrev
= pImpXPolygon
->pPointAry
[nPrev
];
900 Point aDiff
= rNext
- rPrev
;
901 double fNextLen
= CalcDistance(nCenter
, nNext
) / fAbsLen
;
902 double fPrevLen
= CalcDistance(nCenter
, nPrev
) / fAbsLen
;
904 // bei SYMMTR gleiche Laenge fuer beide Seiten
905 if ( GetFlags(nCenter
) == XPOLY_SYMMTR
)
907 fPrevLen
= (fNextLen
+ fPrevLen
) / 2;
910 rNext
.X() = rCenter
.X() + (long) (fNextLen
* aDiff
.X());
911 rNext
.Y() = rCenter
.Y() + (long) (fNextLen
* aDiff
.Y());
912 rPrev
.X() = rCenter
.X() - (long) (fPrevLen
* aDiff
.X());
913 rPrev
.Y() = rCenter
.Y() - (long) (fPrevLen
* aDiff
.Y());
917 /*************************************************************************
919 |* XPolygon::PointsToBezier()
921 |* wandelt vier Polygonpunkte in eine Bezierkurve durch diese Punkte um
923 \************************************************************************/
925 void XPolygon::PointsToBezier(sal_uInt16 nFirst
)
927 double nFullLength
, nPart1Length
, nPart2Length
;
928 double fX0
, fY0
, fX1
, fY1
, fX2
, fY2
, fX3
, fY3
;
929 double fTx1
, fTx2
, fTy1
, fTy2
;
930 double fT1
, fU1
, fT2
, fU2
, fV
;
931 Point
* pPoints
= pImpXPolygon
->pPointAry
;
933 if ( nFirst
> pImpXPolygon
->nPoints
- 4 || IsControl(nFirst
) ||
934 IsControl(nFirst
+1) || IsControl(nFirst
+2) || IsControl(nFirst
+3) )
939 fTx1
= pPoints
[nFirst
+1].X();
940 fTy1
= pPoints
[nFirst
+1].Y();
941 fTx2
= pPoints
[nFirst
+2].X();
942 fTy2
= pPoints
[nFirst
+2].Y();
943 fX0
= pPoints
[nFirst
].X();
944 fY0
= pPoints
[nFirst
].Y();
945 fX3
= pPoints
[nFirst
+3].X();
946 fY3
= pPoints
[nFirst
+3].Y();
948 nPart1Length
= CalcDistance(nFirst
, nFirst
+1);
949 nPart2Length
= nPart1Length
+ CalcDistance(nFirst
+1, nFirst
+2);
950 nFullLength
= nPart2Length
+ CalcDistance(nFirst
+2, nFirst
+3);
951 if ( nFullLength
< 20 )
954 if ( nPart2Length
== nFullLength
)
956 if ( nPart1Length
== nFullLength
)
957 nPart1Length
= nPart2Length
- 1;
958 if ( nPart1Length
<= 0 )
960 if ( nPart2Length
<= 0 || nPart2Length
== nPart1Length
)
961 nPart2Length
= nPart1Length
+ 1;
963 fT1
= nPart1Length
/ nFullLength
;
965 fT2
= nPart2Length
/ nFullLength
;
967 fV
= 3 * (1.0 - (fT1
* fU2
) / (fT2
* fU1
));
969 fX1
= fTx1
/ (fT1
* fU1
* fU1
) - fTx2
* fT1
/ (fT2
* fT2
* fU1
* fU2
);
971 fX1
-= fX0
* ( fU1
/ fT1
+ fU2
/ fT2
) / 3;
972 fX1
+= fX3
* ( fT1
* fT2
/ (fU1
* fU2
)) / 3;
974 fY1
= fTy1
/ (fT1
* fU1
* fU1
) - fTy2
* fT1
/ (fT2
* fT2
* fU1
* fU2
);
976 fY1
-= fY0
* ( fU1
/ fT1
+ fU2
/ fT2
) / 3;
977 fY1
+= fY3
* ( fT1
* fT2
/ (fU1
* fU2
)) / 3;
979 fX2
= fTx2
/ (fT2
* fT2
* fU2
* 3) - fX0
* fU2
* fU2
/ ( fT2
* fT2
* 3);
980 fX2
-= fX1
* fU2
/ fT2
;
981 fX2
-= fX3
* fT2
/ (fU2
* 3);
983 fY2
= fTy2
/ (fT2
* fT2
* fU2
* 3) - fY0
* fU2
* fU2
/ ( fT2
* fT2
* 3);
984 fY2
-= fY1
* fU2
/ fT2
;
985 fY2
-= fY3
* fT2
/ (fU2
* 3);
987 pPoints
[nFirst
+1] = Point((long) fX1
, (long) fY1
);
988 pPoints
[nFirst
+2] = Point((long) fX2
, (long) fY2
);
989 SetFlags(nFirst
+1, XPOLY_CONTROL
);
990 SetFlags(nFirst
+2, XPOLY_CONTROL
);
993 /*************************************************************************
997 |* XPolygon in X- und/oder Y-Richtung skalieren
999 *************************************************************************/
1001 void XPolygon::Scale(double fSx
, double fSy
)
1003 pImpXPolygon
->CheckPointDelete();
1006 sal_uInt16 nPntCnt
= pImpXPolygon
->nPoints
;
1008 for (sal_uInt16 i
= 0; i
< nPntCnt
; i
++)
1010 Point
& rPnt
= pImpXPolygon
->pPointAry
[i
];
1011 rPnt
.X() = (long)(fSx
* rPnt
.X());
1012 rPnt
.Y() = (long)(fSy
* rPnt
.Y());
1016 /*************************************************************************
1018 |* XPolygon::Distort()
1020 |* XPolygon verzerren, indem die Koordinaten relativ zu einem
1021 |* Referenzrechteck in ein beliebiges Viereck skaliert werden
1022 |* Zuordnung der Viereck-Punkte im Polygon zum Referenzrechteck:
1023 |* 0: links oben 0----1
1024 |* 1: rechts oben | |
1025 |* 2: rechts unten 3----2
1028 *************************************************************************/
1030 void XPolygon::Distort(const Rectangle
& rRefRect
,
1031 const XPolygon
& rDistortedRect
)
1033 pImpXPolygon
->CheckPointDelete();
1039 Xr
= rRefRect
.Left();
1040 Yr
= rRefRect
.Top();
1041 Wr
= rRefRect
.GetWidth();
1042 Hr
= rRefRect
.GetHeight();
1046 long X1
, X2
, X3
, X4
;
1047 long Y1
, Y2
, Y3
, Y4
;
1048 DBG_ASSERT(rDistortedRect
.pImpXPolygon
->nPoints
>= 4,
1049 "Distort-Rechteck zu klein");
1051 X1
= rDistortedRect
[0].X();
1052 Y1
= rDistortedRect
[0].Y();
1053 X2
= rDistortedRect
[1].X();
1054 Y2
= rDistortedRect
[1].Y();
1055 X3
= rDistortedRect
[3].X();
1056 Y3
= rDistortedRect
[3].Y();
1057 X4
= rDistortedRect
[2].X();
1058 Y4
= rDistortedRect
[2].Y();
1060 sal_uInt16 nPntCnt
= pImpXPolygon
->nPoints
;
1062 for (sal_uInt16 i
= 0; i
< nPntCnt
; i
++)
1064 double fTx
, fTy
, fUx
, fUy
;
1065 Point
& rPnt
= pImpXPolygon
->pPointAry
[i
];
1067 fTx
= (double)(rPnt
.X() - Xr
) / Wr
;
1068 fTy
= (double)(rPnt
.Y() - Yr
) / Hr
;
1072 rPnt
.X() = (long) ( fUy
* (fUx
* X1
+ fTx
* X2
) +
1073 fTy
* (fUx
* X3
+ fTx
* X4
) );
1074 rPnt
.Y() = (long) ( fUx
* (fUy
* Y1
+ fTy
* Y3
) +
1075 fTx
* (fUy
* Y2
+ fTy
* Y4
) );
1080 basegfx::B2DPolygon
XPolygon::getB2DPolygon() const
1082 // #i74631# use tools Polygon class for conversion to not have the code doubled
1083 // here. This needs one more conversion but avoids different convertors in
1085 DBG_ASSERT(pImpXPolygon
!= 0, "XPolygon::getB2DPolygon(): XPolygon has no implementation incarnated (!)");
1086 const Polygon
aSource(GetPointCount(), pImpXPolygon
->pPointAry
, pImpXPolygon
->pFlagAry
);
1088 return aSource
.getB2DPolygon();
1091 XPolygon::XPolygon(const basegfx::B2DPolygon
& rPolygon
)
1093 // #i74631# use tools Polygon class for conversion to not have the code doubled
1094 // here. This needs one more conversion but avoids different convertors in
1096 DBG_CTOR(XPolygon
,NULL
);
1098 const Polygon
aSource(rPolygon
);
1099 sal_uInt16 nSize
= aSource
.GetSize();
1100 pImpXPolygon
= new ImpXPolygon( nSize
);
1101 pImpXPolygon
->nPoints
= nSize
;
1103 for( sal_uInt16 i
= 0; i
< nSize
; i
++ )
1105 pImpXPolygon
->pPointAry
[i
] = aSource
[i
];
1106 pImpXPolygon
->pFlagAry
[i
] = (sal_uInt8
) aSource
.GetFlags( i
);
1110 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1111 //+--------------- XPolyPolygon -----------------------------------------+
1112 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1114 /*************************************************************************
1116 |* ImpXPolyPolygon::ImpXPolyPolygon()
1118 |* Beschreibung Erzeugt das XPolygon-Array
1120 *************************************************************************/
1122 ImpXPolyPolygon::ImpXPolyPolygon( const ImpXPolyPolygon
& rImpXPolyPoly
) :
1123 aXPolyList( rImpXPolyPoly
.aXPolyList
)
1127 // Einzelne Elemente duplizieren
1128 for ( size_t i
= 0, n
= aXPolyList
.size(); i
< n
; ++i
)
1129 aXPolyList
[ i
] = new XPolygon( *aXPolyList
[ i
] );
1133 /*************************************************************************
1135 |* ImpXPolyPolygon::~ImpXPolyPolygon()
1137 |* Beschreibung Loescht das Polygon-Array
1139 *************************************************************************/
1141 ImpXPolyPolygon::~ImpXPolyPolygon()
1143 for ( size_t i
= 0, n
= aXPolyList
.size(); i
< n
; ++i
)
1144 delete aXPolyList
[ i
];
1148 /*************************************************************************
1150 |* ImpXPolyPolygon::operator==()
1152 *************************************************************************/
1154 bool ImpXPolyPolygon::operator==(const ImpXPolyPolygon
& rImpXPolyPoly
) const
1156 size_t nAnz
= aXPolyList
.size();
1157 const XPolygonList
& rCmpList
= rImpXPolyPoly
.aXPolyList
;
1158 if ( nAnz
!= rCmpList
.size() ) return false;
1160 for ( size_t i
= nAnz
; i
> 0 && bEq
; )
1163 bEq
= ( *aXPolyList
[ i
] == *rCmpList
[ i
] );
1168 /*************************************************************************
1170 |* XPolyPolygon::XPolyPolygon()
1172 *************************************************************************/
1174 XPolyPolygon::XPolyPolygon( sal_uInt16
/*nInitSize*/, sal_uInt16
/*nResize*/ )
1176 DBG_CTOR(XPolyPolygon
,NULL
);
1177 pImpXPolyPolygon
= new ImpXPolyPolygon();
1180 /*************************************************************************
1182 |* XPolyPolygon::XPolyPolygon()
1184 *************************************************************************/
1186 XPolyPolygon::XPolyPolygon( const XPolyPolygon
& rXPolyPoly
)
1188 DBG_CTOR(XPolyPolygon
,NULL
);
1189 pImpXPolyPolygon
= rXPolyPoly
.pImpXPolyPolygon
;
1190 pImpXPolyPolygon
->nRefCount
++;
1193 /*************************************************************************
1195 |* XPolyPolygon::~XPolyPolygon()
1197 *************************************************************************/
1199 XPolyPolygon::~XPolyPolygon()
1201 DBG_DTOR(XPolyPolygon
,NULL
);
1202 if( pImpXPolyPolygon
->nRefCount
> 1 )
1203 pImpXPolyPolygon
->nRefCount
--;
1205 delete pImpXPolyPolygon
;
1208 /*************************************************************************
1210 |* XPolygon::CheckReference()
1212 |* Referenzzaehler desImpXPolyPoly pruefen und ggf. von diesem abkoppeln
1214 *************************************************************************/
1216 void XPolyPolygon::CheckReference()
1218 if( pImpXPolyPolygon
->nRefCount
> 1 )
1220 pImpXPolyPolygon
->nRefCount
--;
1221 pImpXPolyPolygon
= new ImpXPolyPolygon( *pImpXPolyPolygon
);
1225 /*************************************************************************
1227 |* XPolyPolygon::Insert()
1229 *************************************************************************/
1231 void XPolyPolygon::Insert( const XPolygon
& rXPoly
, sal_uInt16 nPos
)
1234 XPolygon
* pXPoly
= new XPolygon( rXPoly
);
1235 if ( nPos
< pImpXPolyPolygon
->aXPolyList
.size() )
1237 XPolygonList::iterator it
= pImpXPolyPolygon
->aXPolyList
.begin();
1238 ::std::advance( it
, nPos
);
1239 pImpXPolyPolygon
->aXPolyList
.insert( it
, pXPoly
);
1242 pImpXPolyPolygon
->aXPolyList
.push_back( pXPoly
);
1245 /*************************************************************************
1247 |* XPolyPolygon::Insert()
1249 |* saemtliche XPolygone aus einem XPolyPolygon einfuegen
1251 *************************************************************************/
1253 void XPolyPolygon::Insert( const XPolyPolygon
& rXPolyPoly
, sal_uInt16 nPos
)
1257 for ( size_t i
= 0; i
< rXPolyPoly
.Count(); i
++)
1259 XPolygon
* pXPoly
= new XPolygon( rXPolyPoly
[i
] );
1261 if ( nPos
< pImpXPolyPolygon
->aXPolyList
.size() )
1263 XPolygonList::iterator it
= pImpXPolyPolygon
->aXPolyList
.begin();
1264 ::std::advance( it
, nPos
);
1265 pImpXPolyPolygon
->aXPolyList
.insert( it
, pXPoly
);
1269 pImpXPolyPolygon
->aXPolyList
.push_back( pXPoly
);
1273 /*************************************************************************
1275 |* XPolyPolygon::Remove()
1277 *************************************************************************/
1279 XPolygon
XPolyPolygon::Remove( sal_uInt16 nPos
)
1282 XPolygonList::iterator it
= pImpXPolyPolygon
->aXPolyList
.begin();
1283 ::std::advance( it
, nPos
);
1284 XPolygon
* pTmpXPoly
= *it
;
1285 pImpXPolyPolygon
->aXPolyList
.erase( it
);
1286 XPolygon
aXPoly( *pTmpXPoly
);
1292 /*************************************************************************
1294 |* XPolyPolygon::GetObject()
1296 *************************************************************************/
1298 const XPolygon
& XPolyPolygon::GetObject( sal_uInt16 nPos
) const
1300 return *(pImpXPolyPolygon
->aXPolyList
[ nPos
]);
1304 /*************************************************************************
1306 |* XPolyPolygon::Clear()
1308 *************************************************************************/
1310 void XPolyPolygon::Clear()
1312 if ( pImpXPolyPolygon
->nRefCount
> 1 )
1314 pImpXPolyPolygon
->nRefCount
--;
1315 pImpXPolyPolygon
= new ImpXPolyPolygon();
1319 for( size_t i
= 0, n
= pImpXPolyPolygon
->aXPolyList
.size(); i
< n
; ++i
)
1320 delete pImpXPolyPolygon
->aXPolyList
[ i
];
1321 pImpXPolyPolygon
->aXPolyList
.clear();
1326 /*************************************************************************
1328 |* XPolyPolygon::Count()
1330 *************************************************************************/
1332 sal_uInt16
XPolyPolygon::Count() const
1334 return (sal_uInt16
)(pImpXPolyPolygon
->aXPolyList
.size());
1337 /*************************************************************************
1339 |* XPolyPolygon::GetBoundRect()
1341 *************************************************************************/
1343 Rectangle
XPolyPolygon::GetBoundRect() const
1345 size_t nXPoly
= pImpXPolyPolygon
->aXPolyList
.size();
1348 for ( size_t n
= 0; n
< nXPoly
; n
++ )
1350 const XPolygon
* pXPoly
= pImpXPolyPolygon
->aXPolyList
[ n
];
1351 aRect
.Union( pXPoly
->GetBoundRect() );
1358 /*************************************************************************
1360 |* XPolyPolygon::operator[]()
1362 *************************************************************************/
1364 XPolygon
& XPolyPolygon::operator[]( sal_uInt16 nPos
)
1367 return *( pImpXPolyPolygon
->aXPolyList
[ nPos
] );
1370 /*************************************************************************
1372 |* XPolyPolygon::operator=()
1374 *************************************************************************/
1376 XPolyPolygon
& XPolyPolygon::operator=( const XPolyPolygon
& rXPolyPoly
)
1378 rXPolyPoly
.pImpXPolyPolygon
->nRefCount
++;
1380 if( pImpXPolyPolygon
->nRefCount
> 1 )
1381 pImpXPolyPolygon
->nRefCount
--;
1383 delete pImpXPolyPolygon
;
1385 pImpXPolyPolygon
= rXPolyPoly
.pImpXPolyPolygon
;
1390 /*************************************************************************
1392 |* XPolyPolygon::operator==()
1394 *************************************************************************/
1396 sal_Bool
XPolyPolygon::operator==( const XPolyPolygon
& rXPolyPoly
) const
1398 if (pImpXPolyPolygon
==rXPolyPoly
.pImpXPolyPolygon
) return sal_True
;
1399 return *pImpXPolyPolygon
== *rXPolyPoly
.pImpXPolyPolygon
;
1403 /*************************************************************************
1405 |* XPolyPolygon::operator!=()
1407 *************************************************************************/
1409 sal_Bool
XPolyPolygon::operator!=( const XPolyPolygon
& rXPolyPoly
) const
1411 if (pImpXPolyPolygon
==rXPolyPoly
.pImpXPolyPolygon
) return sal_False
;
1412 return *pImpXPolyPolygon
!= *rXPolyPoly
.pImpXPolyPolygon
;
1415 /*************************************************************************
1417 |* XPolygon::Distort()
1419 |* XPolygon verzerren, indem die Koordinaten relativ zu einem
1420 |* Referenzrechteck in ein beliebiges Viereck skaliert werden
1421 |* Zuordnung der Viereck-Punkte im Polygon zum Referenzrechteck:
1422 |* 0: links oben 0----1
1423 |* 1: rechts oben | |
1424 |* 2: rechts unten 3----2
1427 *************************************************************************/
1429 void XPolyPolygon::Distort(const Rectangle
& rRefRect
,
1430 const XPolygon
& rDistortedRect
)
1434 for (size_t i
= 0; i
< Count(); i
++)
1435 pImpXPolyPolygon
->aXPolyList
[ i
]->Distort(rRefRect
, rDistortedRect
);
1438 basegfx::B2DPolyPolygon
XPolyPolygon::getB2DPolyPolygon() const
1440 basegfx::B2DPolyPolygon aRetval
;
1442 for(sal_uInt16
a(0L); a
< Count(); a
++)
1444 const XPolygon
& rPoly
= (*this)[a
];
1445 aRetval
.append(rPoly
.getB2DPolygon());
1451 XPolyPolygon::XPolyPolygon(const basegfx::B2DPolyPolygon
& rPolyPolygon
)
1453 DBG_CTOR(XPolyPolygon
,NULL
);
1454 pImpXPolyPolygon
= new ImpXPolyPolygon();
1456 for(sal_uInt32
a(0L); a
< rPolyPolygon
.count(); a
++)
1458 basegfx::B2DPolygon aCandidate
= rPolyPolygon
.getB2DPolygon(a
);
1459 XPolygon
aNewPoly(aCandidate
);
1464 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */