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