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