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