LCOV - code coverage report
Current view: top level - libreoffice/svx/source/xoutdev - _xpoly.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 103 591 17.4 %
Date: 2012-12-27 Functions: 17 61 27.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <osl/endian.h>
      21             : #include <tools/stream.hxx>
      22             : #include <tools/debug.hxx>
      23             : #include <tools/poly.hxx>
      24             : #include <tools/helpers.hxx>
      25             : 
      26             : #include <svx/xpoly.hxx>
      27             : #include "xpolyimp.hxx"
      28             : #include <basegfx/polygon/b2dpolygon.hxx>
      29             : #include <basegfx/point/b2dpoint.hxx>
      30             : #include <basegfx/vector/b2dvector.hxx>
      31             : #include <basegfx/polygon/b2dpolygontools.hxx>
      32             : #include <basegfx/range/b2drange.hxx>
      33             : #include <basegfx/numeric/ftools.hxx>
      34             : 
      35             : DBG_NAME(XPolygon);
      36             : DBG_NAME(XPolyPolygon);
      37             : 
      38             : /*************************************************************************
      39             : |*
      40             : |*    ImpXPolygon::ImpXPolygon()
      41             : |*
      42             : *************************************************************************/
      43             : 
      44         104 : ImpXPolygon::ImpXPolygon( sal_uInt16 nInitSize, sal_uInt16 _nResize )
      45             : {
      46         104 :     pPointAry               = NULL;
      47         104 :     pFlagAry                = NULL;
      48         104 :     bDeleteOldPoints        = sal_False;
      49         104 :     nSize                   = 0;
      50         104 :     nResize                 = _nResize;
      51         104 :     nPoints                 = 0;
      52         104 :     nRefCount               = 1;
      53             : 
      54         104 :     Resize( nInitSize );
      55         104 : }
      56             : 
      57             : /*************************************************************************
      58             : |*
      59             : |*    ImpXPolygon::ImpXPolygon()
      60             : |*
      61             : *************************************************************************/
      62             : 
      63           0 : ImpXPolygon::ImpXPolygon( const ImpXPolygon& rImpXPoly )
      64             : {
      65           0 :     ( (ImpXPolygon&) rImpXPoly ).CheckPointDelete();
      66             : 
      67           0 :     pPointAry               = NULL;
      68           0 :     pFlagAry                = NULL;
      69           0 :     bDeleteOldPoints        = sal_False;
      70           0 :     nSize                   = 0;
      71           0 :     ImpXPolygon::nResize    = rImpXPoly.nResize;
      72           0 :     nPoints                 = 0;
      73           0 :     nRefCount               = 1;
      74             : 
      75           0 :     Resize( rImpXPoly.nSize );
      76             : 
      77             :     // Kopieren
      78           0 :     nPoints = rImpXPoly.nPoints;
      79           0 :     memcpy( pPointAry, rImpXPoly.pPointAry, nSize*sizeof( Point ) );
      80           0 :     memcpy( pFlagAry, rImpXPoly.pFlagAry, nSize );
      81           0 : }
      82             : 
      83             : /*************************************************************************
      84             : |*
      85             : |*    ImpXPolygon::~ImpXPolygon()
      86             : |*
      87             : *************************************************************************/
      88             : 
      89         104 : ImpXPolygon::~ImpXPolygon()
      90             : {
      91         104 :     delete[] (char*) pPointAry;
      92         104 :     delete[] pFlagAry;
      93         104 :     if ( bDeleteOldPoints )
      94           0 :         delete[] (char*) pOldPointAry;
      95         104 : }
      96             : 
      97             : /*************************************************************************
      98             : |*
      99             : |*    ImpXPolygon::operator==()
     100             : |*
     101             : *************************************************************************/
     102             : 
     103             : 
     104           0 : bool ImpXPolygon::operator==(const ImpXPolygon& rImpXPoly) const
     105             : {
     106             :     return nPoints==rImpXPoly.nPoints &&
     107             :            (nPoints==0 ||
     108           0 :             (memcmp(pPointAry,rImpXPoly.pPointAry,nPoints*sizeof(Point))==0 &&
     109           0 :              memcmp(pFlagAry,rImpXPoly.pFlagAry,nPoints)==0));
     110             : }
     111             : 
     112             : /*************************************************************************
     113             : |*
     114             : |*    ImpXPolygon::Resize()
     115             : |*
     116             : |*    !!! Polygongroesse aendern - wenn bDeletePoints sal_False, dann den
     117             : |*    Point-Array nicht loeschen, sondern in pOldPointAry sichern und
     118             : |*    das Flag bDeleteOldPoints setzen. Beim naechsten Zugriff wird
     119             : |*    das Array dann geloescht.
     120             : |*    Damit wird verhindert, dass bei XPoly[n] = XPoly[0] durch ein
     121             : |*    Resize der fuer den rechten Ausdruck verwendete Point-Array
     122             : |*    vorzeitig geloescht wird.
     123             : |*
     124             : *************************************************************************/
     125             : 
     126         104 : void ImpXPolygon::Resize( sal_uInt16 nNewSize, sal_Bool bDeletePoints )
     127             : {
     128         104 :     if( nNewSize == nSize )
     129         104 :         return;
     130             : 
     131         104 :     sal_uInt8*   pOldFlagAry  = pFlagAry;
     132         104 :     sal_uInt16  nOldSize     = nSize;
     133             : 
     134         104 :     CheckPointDelete();
     135         104 :     pOldPointAry = pPointAry;
     136             : 
     137             :     // Neue Groesse auf vielfaches von nResize runden, sofern Objekt
     138             :     // nicht neu angelegt wurde (nSize != 0)
     139         104 :     if ( nSize != 0 && nNewSize > nSize )
     140             :     {
     141             :         DBG_ASSERT(nResize, "Resize-Versuch trotz nResize = 0 !");
     142           0 :         nNewSize = nSize + ((nNewSize-nSize-1) / nResize + 1) * nResize;
     143             :     }
     144             :     // Punkt Array erzeugen
     145         104 :     nSize     = nNewSize;
     146         104 :     pPointAry = (Point*)new char[ nSize*sizeof( Point ) ];
     147         104 :     memset( pPointAry, 0, nSize*sizeof( Point ) );
     148             : 
     149             :     // Flag Array erzeugen
     150         104 :     pFlagAry = new sal_uInt8[ nSize ];
     151         104 :     memset( pFlagAry, 0, nSize );
     152             : 
     153             :     // Eventuell umkopieren
     154         104 :     if( nOldSize )
     155             :     {
     156           0 :         if( nOldSize < nSize )
     157             :         {
     158           0 :             memcpy( pPointAry, pOldPointAry, nOldSize*sizeof( Point ) );
     159           0 :             memcpy( pFlagAry,  pOldFlagAry, nOldSize );
     160             :         }
     161             :         else
     162             :         {
     163           0 :             memcpy( pPointAry, pOldPointAry, nSize*sizeof( Point ) );
     164           0 :             memcpy( pFlagAry, pOldFlagAry, nSize );
     165             : 
     166             :             // Anzahl der gueltigen Punkte anpassen
     167           0 :             if( nPoints > nSize )
     168           0 :                 nPoints = nSize;
     169             :         }
     170           0 :         if ( bDeletePoints )    delete[] (char*) pOldPointAry;
     171           0 :         else                    bDeleteOldPoints = sal_True;
     172           0 :         delete[] pOldFlagAry;
     173             :     }
     174             : }
     175             : 
     176             : 
     177             : /*************************************************************************
     178             : |*
     179             : |*    ImpXPolygon::InsertSpace()
     180             : |*
     181             : *************************************************************************/
     182             : 
     183         240 : void ImpXPolygon::InsertSpace( sal_uInt16 nPos, sal_uInt16 nCount )
     184             : {
     185         240 :     CheckPointDelete();
     186             : 
     187         240 :     if ( nPos > nPoints )
     188           0 :         nPos = nPoints;
     189             : 
     190             :     // Wenn Polygon zu klein dann groesser machen
     191         240 :     if( (nPoints + nCount) > nSize )
     192           0 :         Resize( nPoints + nCount );
     193             : 
     194             :     // Wenn nicht hinter dem letzten Punkt eingefuegt wurde,
     195             :     // den Rest nach hinten schieben
     196         240 :     if( nPos < nPoints )
     197             :     {
     198           0 :         sal_uInt16 nMove = nPoints - nPos;
     199           0 :         memmove( &pPointAry[nPos+nCount], &pPointAry[nPos],
     200           0 :                  nMove * sizeof(Point) );
     201           0 :         memmove( &pFlagAry[nPos+nCount], &pFlagAry[nPos], nMove );
     202             :     }
     203         240 :     memset( &pPointAry[nPos], 0, nCount * sizeof( Point ) );
     204         240 :     memset( &pFlagAry [nPos], 0, nCount );
     205             : 
     206         240 :     nPoints = nPoints + nCount;
     207         240 : }
     208             : 
     209             : 
     210             : /*************************************************************************
     211             : |*
     212             : |*    ImpXPolygon::Remove()
     213             : |*
     214             : *************************************************************************/
     215             : 
     216          96 : void ImpXPolygon::Remove( sal_uInt16 nPos, sal_uInt16 nCount )
     217             : {
     218          96 :     CheckPointDelete();
     219             : 
     220          96 :     if( (nPos + nCount) <= nPoints )
     221             :     {
     222          96 :         sal_uInt16 nMove = nPoints - nPos - nCount;
     223             : 
     224          96 :         if( nMove )
     225             :         {
     226           0 :             memmove( &pPointAry[nPos], &pPointAry[nPos+nCount],
     227           0 :                      nMove * sizeof(Point) );
     228           0 :             memmove( &pFlagAry[nPos], &pFlagAry[nPos+nCount], nMove );
     229             :         }
     230          96 :         memset( &pPointAry[nPoints - nCount], 0, nCount * sizeof( Point ) );
     231          96 :         memset( &pFlagAry [nPoints - nCount], 0, nCount );
     232          96 :         nPoints = nPoints - nCount;
     233             :     }
     234          96 : }
     235             : 
     236             : 
     237             : /*************************************************************************
     238             : |*
     239             : |*    XPolygon::XPolygon()
     240             : |*
     241             : *************************************************************************/
     242             : 
     243         104 : XPolygon::XPolygon( sal_uInt16 nSize, sal_uInt16 nResize )
     244             : {
     245             :     DBG_CTOR(XPolygon,NULL);
     246         104 :     pImpXPolygon = new ImpXPolygon( nSize, nResize );
     247         104 : }
     248             : 
     249             : /*************************************************************************
     250             : |*
     251             : |*    XPolygon::XPolygon()
     252             : |*
     253             : *************************************************************************/
     254             : 
     255          48 : XPolygon::XPolygon( const XPolygon& rXPoly )
     256             : {
     257             :     DBG_CTOR(XPolygon,NULL);
     258          48 :     pImpXPolygon = rXPoly.pImpXPolygon;
     259          48 :     pImpXPolygon->nRefCount++;
     260          48 : }
     261             : 
     262             : /*************************************************************************
     263             : |*
     264             : |*    XPolygon::XPolygon()
     265             : |*
     266             : |*    Rechteck (auch mit abgerundeten Ecken) als Bezierpolygon erzeugen
     267             : |*
     268             : *************************************************************************/
     269             : 
     270           0 : XPolygon::XPolygon(const Rectangle& rRect, long nRx, long nRy)
     271             : {
     272             :     DBG_CTOR(XPolygon,NULL);
     273           0 :     pImpXPolygon = new ImpXPolygon(17);
     274           0 :     long nWh = (rRect.GetWidth()  - 1) / 2;
     275           0 :     long nHh = (rRect.GetHeight() - 1) / 2;
     276             : 
     277           0 :     if ( nRx > nWh )    nRx = nWh;
     278           0 :     if ( nRy > nHh )    nRy = nHh;
     279             : 
     280             :     // Rx negativ, damit Umlauf im Uhrzeigersinn erfolgt
     281           0 :     nRx = -nRx;
     282             : 
     283             :     // Faktor fuer Kontrollpunkte der Bezierkurven: 8/3 * (sin(45g) - 0.5)
     284           0 :     long    nXHdl = (long)(0.552284749 * nRx);
     285           0 :     long    nYHdl = (long)(0.552284749 * nRy);
     286           0 :     sal_uInt16  nPos = 0;
     287             : 
     288           0 :     if ( nRx && nRy )
     289             :     {
     290           0 :         Point aCenter;
     291             : 
     292           0 :         for (sal_uInt16 nQuad = 0; nQuad < 4; nQuad++)
     293             :         {
     294           0 :             switch ( nQuad )
     295             :             {
     296           0 :                 case 0: aCenter = rRect.TopLeft();
     297           0 :                         aCenter.X() -= nRx;
     298           0 :                         aCenter.Y() += nRy;
     299           0 :                         break;
     300           0 :                 case 1: aCenter = rRect.TopRight();
     301           0 :                         aCenter.X() += nRx;
     302           0 :                         aCenter.Y() += nRy;
     303           0 :                         break;
     304           0 :                 case 2: aCenter = rRect.BottomRight();
     305           0 :                         aCenter.X() += nRx;
     306           0 :                         aCenter.Y() -= nRy;
     307           0 :                         break;
     308           0 :                 case 3: aCenter = rRect.BottomLeft();
     309           0 :                         aCenter.X() -= nRx;
     310           0 :                         aCenter.Y() -= nRy;
     311           0 :                         break;
     312             :             }
     313           0 :             GenBezArc(aCenter, nRx, nRy, nXHdl, nYHdl, 0, 900, nQuad, nPos);
     314           0 :             pImpXPolygon->pFlagAry[nPos  ] = (sal_uInt8) XPOLY_SMOOTH;
     315           0 :             pImpXPolygon->pFlagAry[nPos+3] = (sal_uInt8) XPOLY_SMOOTH;
     316           0 :             nPos += 4;
     317           0 :         }
     318             :     }
     319             :     else
     320             :     {
     321           0 :         pImpXPolygon->pPointAry[nPos++] = rRect.TopLeft();
     322           0 :         pImpXPolygon->pPointAry[nPos++] = rRect.TopRight();
     323           0 :         pImpXPolygon->pPointAry[nPos++] = rRect.BottomRight();
     324           0 :         pImpXPolygon->pPointAry[nPos++] = rRect.BottomLeft();
     325             :     }
     326           0 :     pImpXPolygon->pPointAry[nPos] = pImpXPolygon->pPointAry[0];
     327           0 :     pImpXPolygon->nPoints = nPos + 1;
     328           0 : }
     329             : 
     330             : /*************************************************************************
     331             : |*
     332             : |*    XPolygon::XPolygon()
     333             : |*
     334             : |*    Ellipsen(bogen) als Bezierpolygon erzeugen
     335             : |*
     336             : *************************************************************************/
     337             : 
     338           0 : XPolygon::XPolygon(const Point& rCenter, long nRx, long nRy,
     339             :                    sal_uInt16 nStartAngle, sal_uInt16 nEndAngle, sal_Bool bClose)
     340             : {
     341             :     DBG_CTOR(XPolygon,NULL);
     342           0 :     pImpXPolygon = new ImpXPolygon(17);
     343             : 
     344           0 :     nStartAngle %= 3600;
     345           0 :     if ( nEndAngle > 3600 ) nEndAngle %= 3600;
     346           0 :     sal_Bool bFull = (nStartAngle == 0 && nEndAngle == 3600);
     347             : 
     348             :     // Faktor fuer Kontrollpunkte der Bezierkurven: 8/3 * (sin(45g) - 0.5)
     349           0 :     long    nXHdl = (long)(0.552284749 * nRx);
     350           0 :     long    nYHdl = (long)(0.552284749 * nRy);
     351           0 :     sal_uInt16  nPos = 0;
     352           0 :     sal_Bool    bLoopEnd = sal_False;
     353             : 
     354           0 :     do
     355             :     {
     356             :         sal_uInt16 nA1, nA2;
     357           0 :         sal_uInt16 nQuad = nStartAngle / 900;
     358           0 :         if ( nQuad == 4 ) nQuad = 0;
     359           0 :         bLoopEnd = CheckAngles(nStartAngle, nEndAngle, nA1, nA2);
     360           0 :         GenBezArc(rCenter, nRx, nRy, nXHdl, nYHdl, nA1, nA2, nQuad, nPos);
     361           0 :         nPos += 3;
     362           0 :         if ( !bLoopEnd )
     363           0 :             pImpXPolygon->pFlagAry[nPos] = (sal_uInt8) XPOLY_SMOOTH;
     364             : 
     365           0 :     } while ( !bLoopEnd );
     366             : 
     367             :     // Wenn kein Vollkreis, dann ggf. Enden mit Mittelpunkt verbinden
     368           0 :     if ( !bFull && bClose )
     369           0 :         pImpXPolygon->pPointAry[++nPos] = rCenter;
     370             : 
     371           0 :     if ( bFull )
     372             :     {
     373           0 :         pImpXPolygon->pFlagAry[0   ] = (sal_uInt8) XPOLY_SMOOTH;
     374           0 :         pImpXPolygon->pFlagAry[nPos] = (sal_uInt8) XPOLY_SMOOTH;
     375             :     }
     376           0 :     pImpXPolygon->nPoints = nPos + 1;
     377           0 : }
     378             : 
     379             : /*************************************************************************
     380             : |*
     381             : |*    XPolygon::~XPolygon()
     382             : |*
     383             : *************************************************************************/
     384             : 
     385         152 : XPolygon::~XPolygon()
     386             : {
     387             :     DBG_DTOR(XPolygon,NULL);
     388         152 :     if( pImpXPolygon->nRefCount > 1 )
     389          54 :         pImpXPolygon->nRefCount--;
     390             :     else
     391          98 :         delete pImpXPolygon;
     392         152 : }
     393             : 
     394             : /*************************************************************************
     395             : |*
     396             : |*    XPolygon::CheckReference()
     397             : |*
     398             : |*    Referenzzaehler desImpXPoly pruefen und ggf. von diesem abkoppeln
     399             : |*
     400             : *************************************************************************/
     401             : 
     402        1066 : void XPolygon::CheckReference()
     403             : {
     404        1066 :     if( pImpXPolygon->nRefCount > 1 )
     405             :     {
     406           0 :         pImpXPolygon->nRefCount--;
     407           0 :         pImpXPolygon = new ImpXPolygon( *pImpXPolygon );
     408             :     }
     409        1066 : }
     410             : 
     411             : /*************************************************************************
     412             : |*
     413             : |*    XPolygon::SetPointCount()
     414             : |*
     415             : *************************************************************************/
     416             : 
     417           0 : void XPolygon::SetPointCount( sal_uInt16 nPoints )
     418             : {
     419           0 :     pImpXPolygon->CheckPointDelete();
     420           0 :     CheckReference();
     421             : 
     422           0 :     if( pImpXPolygon->nSize < nPoints )
     423           0 :         pImpXPolygon->Resize( nPoints );
     424             : 
     425           0 :     if ( nPoints < pImpXPolygon->nPoints )
     426             :     {
     427           0 :         sal_uInt16 nSize = pImpXPolygon->nPoints - nPoints;
     428           0 :         memset( &pImpXPolygon->pPointAry[nPoints], 0, nSize * sizeof( Point ) );
     429           0 :         memset( &pImpXPolygon->pFlagAry [nPoints], 0, nSize );
     430             :     }
     431           0 :     pImpXPolygon->nPoints = nPoints;
     432           0 : }
     433             : 
     434             : /*************************************************************************
     435             : |*
     436             : |*    XPolygon::GetPointCount()
     437             : |*
     438             : *************************************************************************/
     439             : 
     440         214 : sal_uInt16 XPolygon::GetPointCount() const
     441             : {
     442         214 :     pImpXPolygon->CheckPointDelete();
     443         214 :     return pImpXPolygon->nPoints;
     444             : }
     445             : 
     446             : /*************************************************************************
     447             : |*
     448             : |*    XPolygon::Insert()
     449             : |*
     450             : *************************************************************************/
     451             : 
     452         240 : void XPolygon::Insert( sal_uInt16 nPos, const Point& rPt, XPolyFlags eFlags )
     453             : {
     454         240 :     CheckReference();
     455         240 :     if (nPos>pImpXPolygon->nPoints) nPos=pImpXPolygon->nPoints;
     456         240 :     pImpXPolygon->InsertSpace( nPos, 1 );
     457         240 :     pImpXPolygon->pPointAry[nPos] = rPt;
     458         240 :     pImpXPolygon->pFlagAry[nPos]  = (sal_uInt8)eFlags;
     459         240 : }
     460             : 
     461             : /*************************************************************************
     462             : |*
     463             : |*    XPolygon::Insert()
     464             : |*
     465             : *************************************************************************/
     466             : 
     467           0 : void XPolygon::Insert( sal_uInt16 nPos, const XPolygon& rXPoly )
     468             : {
     469           0 :     CheckReference();
     470           0 :     if (nPos>pImpXPolygon->nPoints) nPos=pImpXPolygon->nPoints;
     471             : 
     472           0 :     sal_uInt16 nPoints = rXPoly.GetPointCount();
     473             : 
     474           0 :     pImpXPolygon->InsertSpace( nPos, nPoints );
     475             : 
     476           0 :     memcpy( &(pImpXPolygon->pPointAry[nPos]),
     477             :             rXPoly.pImpXPolygon->pPointAry,
     478           0 :             nPoints*sizeof( Point ) );
     479           0 :     memcpy( &(pImpXPolygon->pFlagAry[nPos]),
     480             :             rXPoly.pImpXPolygon->pFlagAry,
     481           0 :             nPoints );
     482           0 : }
     483             : 
     484             : /*************************************************************************
     485             : |*
     486             : |*    XPolygon::Remove()
     487             : |*
     488             : *************************************************************************/
     489             : 
     490          96 : void XPolygon::Remove( sal_uInt16 nPos, sal_uInt16 nCount )
     491             : {
     492          96 :     CheckReference();
     493          96 :     pImpXPolygon->Remove( nPos, nCount );
     494          96 : }
     495             : 
     496             : /*************************************************************************
     497             : |*
     498             : |*    XPolygon::Move()
     499             : |*
     500             : *************************************************************************/
     501             : 
     502           0 : void XPolygon::Move( long nHorzMove, long nVertMove )
     503             : {
     504           0 :     if ( !nHorzMove && !nVertMove )
     505           0 :         return;
     506             : 
     507           0 :     CheckReference();
     508             : 
     509             :     // Punkte verschieben
     510           0 :     sal_uInt16 nCount = pImpXPolygon->nPoints;
     511           0 :     for ( sal_uInt16 i = 0; i < nCount; i++ )
     512             :     {
     513           0 :         Point* pPt = &(pImpXPolygon->pPointAry[i]);
     514           0 :         pPt->X() += nHorzMove;
     515           0 :         pPt->Y() += nVertMove;
     516             :     }
     517             : }
     518             : 
     519             : /*************************************************************************
     520             : |*
     521             : |*    XPolygon::GetBoundRect()
     522             : |*
     523             : *************************************************************************/
     524             : 
     525           3 : Rectangle XPolygon::GetBoundRect() const
     526             : {
     527           3 :     pImpXPolygon->CheckPointDelete();
     528           3 :     Rectangle aRetval;
     529             : 
     530           3 :     if(pImpXPolygon->nPoints)
     531             :     {
     532             :         // #i37709#
     533             :         // For historical reasons the control points are not part of the
     534             :         // BoundRect. This makes it necessary to subdivide the polygon to
     535             :         // get a relatively correct BoundRect. Numerically, this is not
     536             :         // correct and never was.
     537             : 
     538           3 :         const basegfx::B2DRange aPolygonRange(basegfx::tools::getRange(getB2DPolygon()));
     539             :         aRetval = Rectangle(
     540             :             FRound(aPolygonRange.getMinX()), FRound(aPolygonRange.getMinY()),
     541           3 :             FRound(aPolygonRange.getMaxX()), FRound(aPolygonRange.getMaxY()));
     542             :     }
     543             : 
     544           3 :     return aRetval;
     545             : }
     546             : 
     547             : /*************************************************************************
     548             : |*
     549             : |*    XPolygon::operator[]()
     550             : |*
     551             : *************************************************************************/
     552             : 
     553           6 : const Point& XPolygon::operator[]( sal_uInt16 nPos ) const
     554             : {
     555             :     DBG_ASSERT(nPos < pImpXPolygon->nPoints, "Ungueltiger Index bei const-Arrayzugriff auf XPolygon");
     556             : 
     557           6 :     pImpXPolygon->CheckPointDelete();
     558           6 :     return pImpXPolygon->pPointAry[nPos];
     559             : }
     560             : 
     561             : /*************************************************************************
     562             : |*
     563             : |*    XPolygon::operator[]()
     564             : |*
     565             : *************************************************************************/
     566             : 
     567         730 : Point& XPolygon::operator[]( sal_uInt16 nPos )
     568             : {
     569         730 :     pImpXPolygon->CheckPointDelete();
     570         730 :     CheckReference();
     571             : 
     572         730 :     if( nPos >= pImpXPolygon->nSize )
     573             :     {
     574             :         DBG_ASSERT(pImpXPolygon->nResize, "Ungueltiger Index bei Arrayzugriff auf XPolygon");
     575           0 :         pImpXPolygon->Resize(nPos + 1, sal_False);
     576             :     }
     577         730 :     if( nPos >= pImpXPolygon->nPoints )
     578           5 :         pImpXPolygon->nPoints = nPos + 1;
     579             : 
     580         730 :     return pImpXPolygon->pPointAry[nPos];
     581             : }
     582             : 
     583             : /*************************************************************************
     584             : |*
     585             : |*    XPolygon::operator=()
     586             : |*
     587             : |*    Beschreibung      Zuweisungsoperator
     588             : |*
     589             : *************************************************************************/
     590             : 
     591           6 : XPolygon& XPolygon::operator=( const XPolygon& rXPoly )
     592             : {
     593           6 :     pImpXPolygon->CheckPointDelete();
     594             : 
     595           6 :     rXPoly.pImpXPolygon->nRefCount++;
     596             : 
     597           6 :     if( pImpXPolygon->nRefCount > 1 )
     598           0 :         pImpXPolygon->nRefCount--;
     599             :     else
     600           6 :         delete pImpXPolygon;
     601             : 
     602           6 :     pImpXPolygon = rXPoly.pImpXPolygon;
     603           6 :     return *this;
     604             : }
     605             : 
     606             : /*************************************************************************
     607             : |*
     608             : |*    XPolygon::operator==()
     609             : |*
     610             : |*    Beschreibung      Gleichheitsoperator
     611             : |*
     612             : *************************************************************************/
     613             : 
     614           0 : sal_Bool XPolygon::operator==( const XPolygon& rXPoly ) const
     615             : {
     616           0 :     pImpXPolygon->CheckPointDelete();
     617           0 :     if (rXPoly.pImpXPolygon==pImpXPolygon) return sal_True;
     618           0 :     return *rXPoly.pImpXPolygon == *pImpXPolygon;
     619             : }
     620             : 
     621             : /*************************************************************************
     622             : |*
     623             : |*    XPolygon::operator!=()
     624             : |*
     625             : |*    Beschreibung      Ungleichheitsoperator
     626             : |*
     627             : *************************************************************************/
     628             : 
     629           0 : sal_Bool XPolygon::operator!=( const XPolygon& rXPoly ) const
     630             : {
     631           0 :     pImpXPolygon->CheckPointDelete();
     632           0 :     if (rXPoly.pImpXPolygon==pImpXPolygon) return sal_False;
     633           0 :     return *rXPoly.pImpXPolygon != *pImpXPolygon;
     634             : }
     635             : 
     636             : /*************************************************************************
     637             : |*
     638             : |*    XPolygon::GetFlags()
     639             : |*
     640             : |*    Flags fuer den Punkt an der Position nPos zurueckgeben
     641             : |*
     642             : *************************************************************************/
     643             : 
     644           0 : XPolyFlags XPolygon::GetFlags( sal_uInt16 nPos ) const
     645             : {
     646           0 :     pImpXPolygon->CheckPointDelete();
     647           0 :     return (XPolyFlags) pImpXPolygon->pFlagAry[nPos];
     648             : }
     649             : 
     650             : /*************************************************************************
     651             : |*
     652             : |*    XPolygon::SetFlags()
     653             : |*
     654             : |*    Flags fuer den Punkt an der Position nPos setzen
     655             : |*
     656             : *************************************************************************/
     657             : 
     658           0 : void XPolygon::SetFlags( sal_uInt16 nPos, XPolyFlags eFlags )
     659             : {
     660           0 :     pImpXPolygon->CheckPointDelete();
     661           0 :     CheckReference();
     662           0 :     pImpXPolygon->pFlagAry[nPos] = (sal_uInt8) eFlags;
     663           0 : }
     664             : 
     665             : /*************************************************************************
     666             : |*
     667             : |*    XPolygon::IsControl()
     668             : |*
     669             : |*    Kurzform zur Abfrage des CONTROL-Flags
     670             : |*
     671             : *************************************************************************/
     672             : 
     673           0 : sal_Bool XPolygon::IsControl(sal_uInt16 nPos) const
     674             : {
     675           0 :     return ( (XPolyFlags) pImpXPolygon->pFlagAry[nPos] == XPOLY_CONTROL );
     676             : }
     677             : 
     678             : /*************************************************************************
     679             : |*
     680             : |*    XPolygon::IsSmooth()
     681             : |*
     682             : |*    Kurzform zur Abfrage von SMOOTH- und SYMMTR-Flag
     683             : |*
     684             : *************************************************************************/
     685             : 
     686           0 : sal_Bool XPolygon::IsSmooth(sal_uInt16 nPos) const
     687             : {
     688           0 :     XPolyFlags eFlag = (XPolyFlags) pImpXPolygon->pFlagAry[nPos];
     689           0 :     return ( eFlag == XPOLY_SMOOTH || eFlag == XPOLY_SYMMTR );
     690             : }
     691             : 
     692             : /*************************************************************************
     693             : |*
     694             : |*    XPolygon::CalcDistance()
     695             : |*
     696             : |*    Abstand zwischen zwei Punkten berechnen
     697             : |*
     698             : *************************************************************************/
     699             : 
     700           0 : double XPolygon::CalcDistance(sal_uInt16 nP1, sal_uInt16 nP2)
     701             : {
     702           0 :     const Point& rP1 = pImpXPolygon->pPointAry[nP1];
     703           0 :     const Point& rP2 = pImpXPolygon->pPointAry[nP2];
     704           0 :     double fDx = rP2.X() - rP1.X();
     705           0 :     double fDy = rP2.Y() - rP1.Y();
     706           0 :     return sqrt(fDx * fDx + fDy * fDy);
     707             : }
     708             : 
     709             : /*************************************************************************
     710             : |*
     711             : |*    XPolygon::SubdivideBezier()
     712             : |*
     713             : |*    Bezierkurve unterteilen
     714             : |*
     715             : *************************************************************************/
     716             : 
     717           0 : void XPolygon::SubdivideBezier(sal_uInt16 nPos, sal_Bool bCalcFirst, double fT)
     718             : {
     719           0 :     Point*  pPoints = pImpXPolygon->pPointAry;
     720           0 :     double  fT2 = fT * fT;
     721           0 :     double  fT3 = fT * fT2;
     722           0 :     double  fU = 1.0 - fT;
     723           0 :     double  fU2 = fU * fU;
     724           0 :     double  fU3 = fU * fU2;
     725           0 :     sal_uInt16  nIdx = nPos;
     726             :     short   nPosInc, nIdxInc;
     727             : 
     728           0 :     if ( bCalcFirst )
     729             :     {
     730           0 :         nPos += 3;
     731           0 :         nPosInc = -1;
     732           0 :         nIdxInc = 0;
     733             :     }
     734             :     else
     735             :     {
     736           0 :         nPosInc = 1;
     737           0 :         nIdxInc = 1;
     738             :     }
     739           0 :     pPoints[nPos].X() = (long) (fU3 *       pPoints[nIdx  ].X() +
     740           0 :                                 fT  * fU2 * pPoints[nIdx+1].X() * 3 +
     741           0 :                                 fT2 * fU  * pPoints[nIdx+2].X() * 3 +
     742           0 :                                 fT3 *       pPoints[nIdx+3].X());
     743           0 :     pPoints[nPos].Y() = (long) (fU3 *       pPoints[nIdx  ].Y() +
     744           0 :                                 fT  * fU2 * pPoints[nIdx+1].Y() * 3 +
     745           0 :                                 fT2 * fU  * pPoints[nIdx+2].Y() * 3 +
     746           0 :                                 fT3 *       pPoints[nIdx+3].Y());
     747           0 :     nPos = nPos + nPosInc;
     748           0 :     nIdx = nIdx + nIdxInc;
     749           0 :     pPoints[nPos].X() = (long) (fU2 *       pPoints[nIdx  ].X() +
     750           0 :                                 fT  * fU *  pPoints[nIdx+1].X() * 2 +
     751           0 :                                 fT2 *       pPoints[nIdx+2].X());
     752           0 :     pPoints[nPos].Y() = (long) (fU2 *       pPoints[nIdx  ].Y() +
     753           0 :                                 fT  * fU *  pPoints[nIdx+1].Y() * 2 +
     754           0 :                                 fT2 *       pPoints[nIdx+2].Y());
     755           0 :     nPos = nPos + nPosInc;
     756           0 :     nIdx = nIdx + nIdxInc;
     757           0 :     pPoints[nPos].X() = (long) (fU * pPoints[nIdx  ].X() +
     758           0 :                                 fT * pPoints[nIdx+1].X());
     759           0 :     pPoints[nPos].Y() = (long) (fU * pPoints[nIdx  ].Y() +
     760           0 :                                 fT * pPoints[nIdx+1].Y());
     761           0 : }
     762             : 
     763             : /************************************************************************/
     764             : 
     765           0 : void XPolygon::GenBezArc(const Point& rCenter, long nRx, long nRy,
     766             :                          long nXHdl, long nYHdl, sal_uInt16 nStart, sal_uInt16 nEnd,
     767             :                          sal_uInt16 nQuad, sal_uInt16 nFirst)
     768             : {
     769           0 :     Point* pPoints = pImpXPolygon->pPointAry;
     770           0 :     pPoints[nFirst  ] = rCenter;
     771           0 :     pPoints[nFirst+3] = rCenter;
     772             : 
     773           0 :     if ( nQuad == 1 || nQuad == 2 )
     774             :     {
     775           0 :         nRx   = -nRx; nXHdl = -nXHdl;
     776             :     }
     777           0 :     if ( nQuad == 0 || nQuad == 1 )
     778             :     {
     779           0 :         nRy   = -nRy; nYHdl = -nYHdl;
     780             :     }
     781             : 
     782           0 :     if ( nQuad == 0 || nQuad == 2 )
     783             :     {
     784           0 :         pPoints[nFirst].X() += nRx; pPoints[nFirst+3].Y() += nRy;
     785             :     }
     786             :     else
     787             :     {
     788           0 :         pPoints[nFirst].Y() += nRy; pPoints[nFirst+3].X() += nRx;
     789             :     }
     790           0 :     pPoints[nFirst+1] = pPoints[nFirst];
     791           0 :     pPoints[nFirst+2] = pPoints[nFirst+3];
     792             : 
     793           0 :     if ( nQuad == 0 || nQuad == 2 )
     794             :     {
     795           0 :         pPoints[nFirst+1].Y() += nYHdl; pPoints[nFirst+2].X() += nXHdl;
     796             :     }
     797             :     else
     798             :     {
     799           0 :         pPoints[nFirst+1].X() += nXHdl; pPoints[nFirst+2].Y() += nYHdl;
     800             :     }
     801           0 :     if ( nStart > 0 )
     802           0 :         SubdivideBezier(nFirst, sal_False, (double)nStart / 900);
     803           0 :     if ( nEnd < 900 )
     804           0 :         SubdivideBezier(nFirst, sal_True, (double)(nEnd-nStart) / (900-nStart));
     805           0 :     SetFlags(nFirst+1, XPOLY_CONTROL);
     806           0 :     SetFlags(nFirst+2, XPOLY_CONTROL);
     807           0 : }
     808             : 
     809             : /************************************************************************/
     810             : 
     811           0 : sal_Bool XPolygon::CheckAngles(sal_uInt16& nStart, sal_uInt16 nEnd, sal_uInt16& nA1, sal_uInt16& nA2)
     812             : {
     813           0 :     if ( nStart == 3600 ) nStart = 0;
     814           0 :     if ( nEnd == 0 ) nEnd = 3600;
     815           0 :     sal_uInt16 nStPrev = nStart;
     816           0 :     sal_uInt16 nMax = (nStart / 900 + 1) * 900;
     817           0 :     sal_uInt16 nMin = nMax - 900;
     818             : 
     819           0 :     if ( nEnd >= nMax || nEnd <= nStart )   nA2 = 900;
     820           0 :     else                                    nA2 = nEnd - nMin;
     821           0 :     nA1 = nStart - nMin;
     822           0 :     nStart = nMax;
     823             : 
     824             :     // sal_True zurueck, falls letztes Segment berechnet wurde
     825           0 :     return (nStPrev < nEnd && nStart >= nEnd);
     826             : }
     827             : 
     828             : /*************************************************************************
     829             : |*
     830             : |*    XPolygon::CalcSmoothJoin()
     831             : |*
     832             : |*    glatten Uebergang zu einer Bezierkurve berechnen, indem der
     833             : |*    entsprechende Punkt auf die Verbindungslinie von zwei anderen
     834             : |*    Punkten projiziert wird
     835             : |*     Center = End- bzw. Anfangspunkt der Bezierkurve
     836             : |*     Drag   = der bewegte Punkt, der die Verschiebung von Pnt vorgibt
     837             : |*     Pnt    = der zu modifizierende Punkt
     838             : |*    Wenn Center am Anfang bzw. Ende des Polygons liegt, wird Pnt
     839             : |*    auf die entgegengesetzte Seite verlegt
     840             : |*
     841             : \************************************************************************/
     842             : 
     843           0 : void XPolygon::CalcSmoothJoin(sal_uInt16 nCenter, sal_uInt16 nDrag, sal_uInt16 nPnt)
     844             : {
     845           0 :     CheckReference();
     846             : 
     847             : //  sal_uInt16  nMaxPnt = pImpXPolygon->nPoints - 1;
     848             : 
     849             : //  if ( nCenter == nMaxPnt )   nPnt = 1;
     850             : //  else if ( nCenter == 0 )    nPnt = nMaxPnt - 1;
     851             : 
     852             :     // Wenn nPnt kein Control-Punkt, d.h. nicht verschiebbar, dann
     853             :     // statt dessen nDrag auf der Achse nCenter-nPnt verschieben
     854           0 :     if ( !IsControl(nPnt) )
     855             :     {
     856           0 :         sal_uInt16 nTmp = nDrag;
     857           0 :         nDrag = nPnt;
     858           0 :         nPnt = nTmp;
     859             :     }
     860           0 :     Point*  pPoints = pImpXPolygon->pPointAry;
     861           0 :     Point   aDiff   = pPoints[nDrag] - pPoints[nCenter];
     862           0 :     double  fDiv    = CalcDistance(nCenter, nDrag);
     863             : 
     864           0 :     if ( fDiv )
     865             :     {
     866           0 :         double fRatio = CalcDistance(nCenter, nPnt) / fDiv;
     867             :         // bei SMOOTH bisherige Laenge beibehalten
     868           0 :         if ( GetFlags(nCenter) == XPOLY_SMOOTH || !IsControl(nDrag) )
     869             :         {
     870           0 :             aDiff.X() = (long) (fRatio * aDiff.X());
     871           0 :             aDiff.Y() = (long) (fRatio * aDiff.Y());
     872             :         }
     873           0 :         pPoints[nPnt] = pPoints[nCenter] - aDiff;
     874             :     }
     875           0 : }
     876             : 
     877             : /*************************************************************************
     878             : |*
     879             : |*    XPolygon::CalcTangent()
     880             : |*
     881             : |*    Tangente fuer den Uebergang zwischen zwei Bezierkurven berechnen
     882             : |*     Center = End- bzw. Anfangspunkt der Bezierkurven
     883             : |*     Prev   = vorheriger Zugpunkt
     884             : |*     Next   = naechster Zugpunkt
     885             : |*
     886             : \************************************************************************/
     887             : 
     888           0 : void XPolygon::CalcTangent(sal_uInt16 nCenter, sal_uInt16 nPrev, sal_uInt16 nNext)
     889             : {
     890           0 :     CheckReference();
     891             : 
     892           0 :     double fAbsLen = CalcDistance(nNext, nPrev);
     893             : 
     894           0 :     if ( fAbsLen )
     895             :     {
     896           0 :         const Point& rCenter = pImpXPolygon->pPointAry[nCenter];
     897           0 :         Point&  rNext = pImpXPolygon->pPointAry[nNext];
     898           0 :         Point&  rPrev = pImpXPolygon->pPointAry[nPrev];
     899           0 :         Point   aDiff = rNext - rPrev;
     900           0 :         double  fNextLen = CalcDistance(nCenter, nNext) / fAbsLen;
     901           0 :         double  fPrevLen = CalcDistance(nCenter, nPrev) / fAbsLen;
     902             : 
     903             :         // bei SYMMTR gleiche Laenge fuer beide Seiten
     904           0 :         if ( GetFlags(nCenter) == XPOLY_SYMMTR )
     905             :         {
     906           0 :             fPrevLen = (fNextLen + fPrevLen) / 2;
     907           0 :             fNextLen = fPrevLen;
     908             :         }
     909           0 :         rNext.X() = rCenter.X() + (long) (fNextLen * aDiff.X());
     910           0 :         rNext.Y() = rCenter.Y() + (long) (fNextLen * aDiff.Y());
     911           0 :         rPrev.X() = rCenter.X() - (long) (fPrevLen * aDiff.X());
     912           0 :         rPrev.Y() = rCenter.Y() - (long) (fPrevLen * aDiff.Y());
     913             :     }
     914           0 : }
     915             : 
     916             : /*************************************************************************
     917             : |*
     918             : |*    XPolygon::PointsToBezier()
     919             : |*
     920             : |*    wandelt vier Polygonpunkte in eine Bezierkurve durch diese Punkte um
     921             : |*
     922             : \************************************************************************/
     923             : 
     924           0 : void XPolygon::PointsToBezier(sal_uInt16 nFirst)
     925             : {
     926             :     double  nFullLength, nPart1Length, nPart2Length;
     927             :     double  fX0, fY0, fX1, fY1, fX2, fY2, fX3, fY3;
     928             :     double  fTx1, fTx2, fTy1, fTy2;
     929             :     double  fT1, fU1, fT2, fU2, fV;
     930           0 :     Point*  pPoints = pImpXPolygon->pPointAry;
     931             : 
     932           0 :     if ( nFirst > pImpXPolygon->nPoints - 4 || IsControl(nFirst) ||
     933           0 :          IsControl(nFirst+1) || IsControl(nFirst+2) || IsControl(nFirst+3) )
     934           0 :         return;
     935             : 
     936           0 :     CheckReference();
     937             : 
     938           0 :     fTx1 = pPoints[nFirst+1].X();
     939           0 :     fTy1 = pPoints[nFirst+1].Y();
     940           0 :     fTx2 = pPoints[nFirst+2].X();
     941           0 :     fTy2 = pPoints[nFirst+2].Y();
     942           0 :     fX0  = pPoints[nFirst  ].X();
     943           0 :     fY0  = pPoints[nFirst  ].Y();
     944           0 :     fX3  = pPoints[nFirst+3].X();
     945           0 :     fY3  = pPoints[nFirst+3].Y();
     946             : 
     947           0 :     nPart1Length = CalcDistance(nFirst, nFirst+1);
     948           0 :     nPart2Length = nPart1Length + CalcDistance(nFirst+1, nFirst+2);
     949           0 :     nFullLength  = nPart2Length + CalcDistance(nFirst+2, nFirst+3);
     950           0 :     if ( nFullLength < 20 )
     951           0 :         return;
     952             : 
     953           0 :     if ( nPart2Length == nFullLength )
     954           0 :         nPart2Length -= 1;
     955           0 :     if ( nPart1Length == nFullLength )
     956           0 :         nPart1Length = nPart2Length - 1;
     957           0 :     if ( nPart1Length <= 0 )
     958           0 :         nPart1Length = 1;
     959           0 :     if ( nPart2Length <= 0 || nPart2Length == nPart1Length )
     960           0 :         nPart2Length = nPart1Length + 1;
     961             : 
     962           0 :     fT1 = nPart1Length / nFullLength;
     963           0 :     fU1 = 1.0 - fT1;
     964           0 :     fT2 = nPart2Length / nFullLength;
     965           0 :     fU2 = 1.0 - fT2;
     966           0 :     fV = 3 * (1.0 - (fT1 * fU2) / (fT2 * fU1));
     967             : 
     968           0 :     fX1 = fTx1 / (fT1 * fU1 * fU1) - fTx2 * fT1 / (fT2 * fT2 * fU1 * fU2);
     969           0 :     fX1 /= fV;
     970           0 :     fX1 -= fX0 * ( fU1 / fT1 + fU2 / fT2) / 3;
     971           0 :     fX1 += fX3 * ( fT1 * fT2 / (fU1 * fU2)) / 3;
     972             : 
     973           0 :     fY1 = fTy1 / (fT1 * fU1 * fU1) - fTy2 * fT1 / (fT2 * fT2 * fU1 * fU2);
     974           0 :     fY1 /= fV;
     975           0 :     fY1 -= fY0 * ( fU1 / fT1 + fU2 / fT2) / 3;
     976           0 :     fY1 += fY3 * ( fT1 * fT2 / (fU1 * fU2)) / 3;
     977             : 
     978           0 :     fX2 = fTx2 / (fT2 * fT2 * fU2 * 3) - fX0 * fU2 * fU2 / ( fT2 * fT2 * 3);
     979           0 :     fX2 -= fX1 * fU2 / fT2;
     980           0 :     fX2 -= fX3 * fT2 / (fU2 * 3);
     981             : 
     982           0 :     fY2 = fTy2 / (fT2 * fT2 * fU2 * 3) - fY0 * fU2 * fU2 / ( fT2 * fT2 * 3);
     983           0 :     fY2 -= fY1 * fU2 / fT2;
     984           0 :     fY2 -= fY3 * fT2 / (fU2 * 3);
     985             : 
     986           0 :     pPoints[nFirst+1] = Point((long) fX1, (long) fY1);
     987           0 :     pPoints[nFirst+2] = Point((long) fX2, (long) fY2);
     988           0 :     SetFlags(nFirst+1, XPOLY_CONTROL);
     989           0 :     SetFlags(nFirst+2, XPOLY_CONTROL);
     990             : }
     991             : 
     992             : /*************************************************************************
     993             : |*
     994             : |*    XPolygon::Scale()
     995             : |*
     996             : |*    XPolygon in X- und/oder Y-Richtung skalieren
     997             : |*
     998             : *************************************************************************/
     999             : 
    1000           0 : void XPolygon::Scale(double fSx, double fSy)
    1001             : {
    1002           0 :     pImpXPolygon->CheckPointDelete();
    1003           0 :     CheckReference();
    1004             : 
    1005           0 :     sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
    1006             : 
    1007           0 :     for (sal_uInt16 i = 0; i < nPntCnt; i++)
    1008             :     {
    1009           0 :         Point& rPnt = pImpXPolygon->pPointAry[i];
    1010           0 :         rPnt.X() = (long)(fSx * rPnt.X());
    1011           0 :         rPnt.Y() = (long)(fSy * rPnt.Y());
    1012             :     }
    1013           0 : }
    1014             : 
    1015             : /*************************************************************************
    1016             : |*
    1017             : |*    XPolygon::Distort()
    1018             : |*
    1019             : |*    XPolygon verzerren, indem die Koordinaten relativ zu einem
    1020             : |*    Referenzrechteck in ein beliebiges Viereck skaliert werden
    1021             : |*    Zuordnung der Viereck-Punkte im Polygon zum Referenzrechteck:
    1022             : |*    0: links oben      0----1
    1023             : |*    1: rechts oben     |    |
    1024             : |*    2: rechts unten    3----2
    1025             : |*    3: links unten
    1026             : |*
    1027             : *************************************************************************/
    1028             : 
    1029           0 : void XPolygon::Distort(const Rectangle& rRefRect,
    1030             :                        const XPolygon& rDistortedRect)
    1031             : {
    1032           0 :     pImpXPolygon->CheckPointDelete();
    1033           0 :     CheckReference();
    1034             : 
    1035             :     long    Xr, Wr;
    1036             :     long    Yr, Hr;
    1037             : 
    1038           0 :     Xr = rRefRect.Left();
    1039           0 :     Yr = rRefRect.Top();
    1040           0 :     Wr = rRefRect.GetWidth();
    1041           0 :     Hr = rRefRect.GetHeight();
    1042             : 
    1043           0 :     if ( Wr && Hr )
    1044             :     {
    1045             :         long    X1, X2, X3, X4;
    1046             :         long    Y1, Y2, Y3, Y4;
    1047             :         DBG_ASSERT(rDistortedRect.pImpXPolygon->nPoints >= 4,
    1048             :                    "Distort-Rechteck zu klein");
    1049             : 
    1050           0 :         X1 = rDistortedRect[0].X();
    1051           0 :         Y1 = rDistortedRect[0].Y();
    1052           0 :         X2 = rDistortedRect[1].X();
    1053           0 :         Y2 = rDistortedRect[1].Y();
    1054           0 :         X3 = rDistortedRect[3].X();
    1055           0 :         Y3 = rDistortedRect[3].Y();
    1056           0 :         X4 = rDistortedRect[2].X();
    1057           0 :         Y4 = rDistortedRect[2].Y();
    1058             : 
    1059           0 :         sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
    1060             : 
    1061           0 :         for (sal_uInt16 i = 0; i < nPntCnt; i++)
    1062             :         {
    1063             :             double  fTx, fTy, fUx, fUy;
    1064           0 :             Point& rPnt = pImpXPolygon->pPointAry[i];
    1065             : 
    1066           0 :             fTx = (double)(rPnt.X() - Xr) / Wr;
    1067           0 :             fTy = (double)(rPnt.Y() - Yr) / Hr;
    1068           0 :             fUx = 1.0 - fTx;
    1069           0 :             fUy = 1.0 - fTy;
    1070             : 
    1071           0 :             rPnt.X() = (long) ( fUy * (fUx * X1 + fTx * X2) +
    1072           0 :                                 fTy * (fUx * X3 + fTx * X4) );
    1073           0 :             rPnt.Y() = (long) ( fUx * (fUy * Y1 + fTy * Y3) +
    1074           0 :                                 fTx * (fUy * Y2 + fTy * Y4) );
    1075             :         }
    1076             :     }
    1077           0 : }
    1078             : 
    1079           6 : basegfx::B2DPolygon XPolygon::getB2DPolygon() const
    1080             : {
    1081             :     // #i74631# use tools Polygon class for conversion to not have the code doubled
    1082             :     // here. This needs one more conversion but avoids different convertors in
    1083             :     // the long run
    1084             :     DBG_ASSERT(pImpXPolygon != 0, "XPolygon::getB2DPolygon(): XPolygon has no implementation incarnated (!)");
    1085           6 :     const Polygon aSource(GetPointCount(), pImpXPolygon->pPointAry, pImpXPolygon->pFlagAry);
    1086             : 
    1087           6 :     return aSource.getB2DPolygon();
    1088             : }
    1089             : 
    1090           0 : XPolygon::XPolygon(const basegfx::B2DPolygon& rPolygon)
    1091             : {
    1092             :     // #i74631# use tools Polygon class for conversion to not have the code doubled
    1093             :     // here. This needs one more conversion but avoids different convertors in
    1094             :     // the long run
    1095             :     DBG_CTOR(XPolygon,NULL);
    1096             : 
    1097           0 :     const Polygon aSource(rPolygon);
    1098           0 :     sal_uInt16 nSize = aSource.GetSize();
    1099           0 :     pImpXPolygon = new ImpXPolygon( nSize );
    1100           0 :     pImpXPolygon->nPoints = nSize;
    1101             : 
    1102           0 :     for( sal_uInt16 i = 0; i < nSize;  i++ )
    1103             :     {
    1104           0 :         pImpXPolygon->pPointAry[i] = aSource[i];
    1105           0 :         pImpXPolygon->pFlagAry[i] = (sal_uInt8) aSource.GetFlags( i );
    1106           0 :     }
    1107           0 : }
    1108             : 
    1109             : //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    1110             : //+--------------- XPolyPolygon -----------------------------------------+
    1111             : //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    1112             : 
    1113             : /*************************************************************************
    1114             : |*
    1115             : |*    ImpXPolyPolygon::ImpXPolyPolygon()
    1116             : |*
    1117             : |*    Beschreibung      Erzeugt das XPolygon-Array
    1118             : |*
    1119             : *************************************************************************/
    1120             : 
    1121           0 : ImpXPolyPolygon::ImpXPolyPolygon( const ImpXPolyPolygon& rImpXPolyPoly ) :
    1122           0 :                      aXPolyList( rImpXPolyPoly.aXPolyList )
    1123             : {
    1124           0 :     nRefCount = 1;
    1125             : 
    1126             :     // Einzelne Elemente duplizieren
    1127           0 :     for ( size_t i = 0, n = aXPolyList.size(); i < n; ++i )
    1128           0 :         aXPolyList[ i ] = new XPolygon( *aXPolyList[ i ] );
    1129           0 : }
    1130             : 
    1131             : 
    1132             : /*************************************************************************
    1133             : |*
    1134             : |*    ImpXPolyPolygon::~ImpXPolyPolygon()
    1135             : |*
    1136             : |*    Beschreibung      Loescht das Polygon-Array
    1137             : |*
    1138             : *************************************************************************/
    1139             : 
    1140           0 : ImpXPolyPolygon::~ImpXPolyPolygon()
    1141             : {
    1142           0 :     for ( size_t i = 0, n = aXPolyList.size(); i < n; ++i )
    1143           0 :         delete aXPolyList[ i ];
    1144           0 :     aXPolyList.clear();
    1145           0 : }
    1146             : 
    1147             : /*************************************************************************
    1148             : |*
    1149             : |*    ImpXPolyPolygon::operator==()
    1150             : |*
    1151             : *************************************************************************/
    1152             : 
    1153           0 : bool ImpXPolyPolygon::operator==(const ImpXPolyPolygon& rImpXPolyPoly) const
    1154             : {
    1155           0 :     size_t nAnz = aXPolyList.size();
    1156           0 :     const XPolygonList& rCmpList = rImpXPolyPoly.aXPolyList;
    1157           0 :     if ( nAnz != rCmpList.size() ) return false;
    1158           0 :     bool bEq=true;
    1159           0 :     for ( size_t i = nAnz; i > 0 && bEq; )
    1160             :     {
    1161           0 :         i--;
    1162           0 :         bEq = ( *aXPolyList[ i ] == *rCmpList[ i ] );
    1163             :     }
    1164           0 :     return bEq;
    1165             : }
    1166             : 
    1167             : /*************************************************************************
    1168             : |*
    1169             : |*    XPolyPolygon::XPolyPolygon()
    1170             : |*
    1171             : *************************************************************************/
    1172             : 
    1173           0 : XPolyPolygon::XPolyPolygon( sal_uInt16 /*nInitSize*/, sal_uInt16 /*nResize*/ )
    1174             : {
    1175             :     DBG_CTOR(XPolyPolygon,NULL);
    1176           0 :     pImpXPolyPolygon = new ImpXPolyPolygon();
    1177           0 : }
    1178             : 
    1179             : /*************************************************************************
    1180             : |*
    1181             : |*    XPolyPolygon::XPolyPolygon()
    1182             : |*
    1183             : *************************************************************************/
    1184             : 
    1185           0 : XPolyPolygon::XPolyPolygon( const XPolyPolygon& rXPolyPoly )
    1186             : {
    1187             :     DBG_CTOR(XPolyPolygon,NULL);
    1188           0 :     pImpXPolyPolygon = rXPolyPoly.pImpXPolyPolygon;
    1189           0 :     pImpXPolyPolygon->nRefCount++;
    1190           0 : }
    1191             : 
    1192             : /*************************************************************************
    1193             : |*
    1194             : |*    XPolyPolygon::~XPolyPolygon()
    1195             : |*
    1196             : *************************************************************************/
    1197             : 
    1198           0 : XPolyPolygon::~XPolyPolygon()
    1199             : {
    1200             :     DBG_DTOR(XPolyPolygon,NULL);
    1201           0 :     if( pImpXPolyPolygon->nRefCount > 1 )
    1202           0 :         pImpXPolyPolygon->nRefCount--;
    1203             :     else
    1204           0 :         delete pImpXPolyPolygon;
    1205           0 : }
    1206             : 
    1207             : /*************************************************************************
    1208             : |*
    1209             : |*    XPolygon::CheckReference()
    1210             : |*
    1211             : |*    Referenzzaehler desImpXPolyPoly pruefen und ggf. von diesem abkoppeln
    1212             : |*
    1213             : *************************************************************************/
    1214             : 
    1215           0 : void XPolyPolygon::CheckReference()
    1216             : {
    1217           0 :     if( pImpXPolyPolygon->nRefCount > 1 )
    1218             :     {
    1219           0 :         pImpXPolyPolygon->nRefCount--;
    1220           0 :         pImpXPolyPolygon = new ImpXPolyPolygon( *pImpXPolyPolygon );
    1221             :     }
    1222           0 : }
    1223             : 
    1224             : /*************************************************************************
    1225             : |*
    1226             : |*    XPolyPolygon::Insert()
    1227             : |*
    1228             : *************************************************************************/
    1229             : 
    1230           0 : void XPolyPolygon::Insert( const XPolygon& rXPoly, sal_uInt16 nPos )
    1231             : {
    1232           0 :     CheckReference();
    1233           0 :     XPolygon* pXPoly = new XPolygon( rXPoly );
    1234           0 :     if ( nPos < pImpXPolyPolygon->aXPolyList.size() )
    1235             :     {
    1236           0 :         XPolygonList::iterator it = pImpXPolyPolygon->aXPolyList.begin();
    1237           0 :         ::std::advance( it, nPos );
    1238           0 :         pImpXPolyPolygon->aXPolyList.insert( it, pXPoly );
    1239             :     }
    1240             :     else
    1241           0 :         pImpXPolyPolygon->aXPolyList.push_back( pXPoly );
    1242           0 : }
    1243             : 
    1244             : /*************************************************************************
    1245             : |*
    1246             : |*    XPolyPolygon::Insert()
    1247             : |*
    1248             : |*    saemtliche XPolygone aus einem XPolyPolygon einfuegen
    1249             : |*
    1250             : *************************************************************************/
    1251             : 
    1252           0 : void XPolyPolygon::Insert( const XPolyPolygon& rXPolyPoly, sal_uInt16 nPos )
    1253             : {
    1254           0 :     CheckReference();
    1255             : 
    1256           0 :     for ( size_t i = 0; i < rXPolyPoly.Count(); i++)
    1257             :     {
    1258           0 :         XPolygon* pXPoly = new XPolygon( rXPolyPoly[i] );
    1259             : 
    1260           0 :         if ( nPos < pImpXPolyPolygon->aXPolyList.size() )
    1261             :         {
    1262           0 :             XPolygonList::iterator it = pImpXPolyPolygon->aXPolyList.begin();
    1263           0 :             ::std::advance( it, nPos );
    1264           0 :             pImpXPolyPolygon->aXPolyList.insert( it, pXPoly );
    1265           0 :             nPos++;
    1266             :         }
    1267             :         else
    1268           0 :             pImpXPolyPolygon->aXPolyList.push_back( pXPoly );
    1269             :     }
    1270           0 : }
    1271             : 
    1272             : /*************************************************************************
    1273             : |*
    1274             : |*    XPolyPolygon::Remove()
    1275             : |*
    1276             : *************************************************************************/
    1277             : 
    1278           0 : XPolygon XPolyPolygon::Remove( sal_uInt16 nPos )
    1279             : {
    1280           0 :     CheckReference();
    1281           0 :     XPolygonList::iterator it = pImpXPolyPolygon->aXPolyList.begin();
    1282           0 :     ::std::advance( it, nPos );
    1283           0 :     XPolygon* pTmpXPoly = *it;
    1284           0 :     pImpXPolyPolygon->aXPolyList.erase( it );
    1285           0 :     XPolygon  aXPoly( *pTmpXPoly );
    1286           0 :     delete pTmpXPoly;
    1287           0 :     return aXPoly;
    1288             : }
    1289             : 
    1290             : 
    1291             : /*************************************************************************
    1292             : |*
    1293             : |*    XPolyPolygon::GetObject()
    1294             : |*
    1295             : *************************************************************************/
    1296             : 
    1297           0 : const XPolygon& XPolyPolygon::GetObject( sal_uInt16 nPos ) const
    1298             : {
    1299           0 :     return *(pImpXPolyPolygon->aXPolyList[ nPos ]);
    1300             : }
    1301             : 
    1302             : 
    1303             : /*************************************************************************
    1304             : |*
    1305             : |*    XPolyPolygon::Clear()
    1306             : |*
    1307             : *************************************************************************/
    1308             : 
    1309           0 : void XPolyPolygon::Clear()
    1310             : {
    1311           0 :     if ( pImpXPolyPolygon->nRefCount > 1 )
    1312             :     {
    1313           0 :         pImpXPolyPolygon->nRefCount--;
    1314           0 :         pImpXPolyPolygon = new ImpXPolyPolygon();
    1315             :     }
    1316             :     else
    1317             :     {
    1318           0 :         for( size_t i = 0, n = pImpXPolyPolygon->aXPolyList.size(); i < n; ++i )
    1319           0 :             delete pImpXPolyPolygon->aXPolyList[ i ];
    1320           0 :         pImpXPolyPolygon->aXPolyList.clear();
    1321             :     }
    1322           0 : }
    1323             : 
    1324             : 
    1325             : /*************************************************************************
    1326             : |*
    1327             : |*    XPolyPolygon::Count()
    1328             : |*
    1329             : *************************************************************************/
    1330             : 
    1331           0 : sal_uInt16 XPolyPolygon::Count() const
    1332             : {
    1333           0 :     return (sal_uInt16)(pImpXPolyPolygon->aXPolyList.size());
    1334             : }
    1335             : 
    1336             : /*************************************************************************
    1337             : |*
    1338             : |*    XPolyPolygon::GetBoundRect()
    1339             : |*
    1340             : *************************************************************************/
    1341             : 
    1342           0 : Rectangle XPolyPolygon::GetBoundRect() const
    1343             : {
    1344           0 :     size_t nXPoly = pImpXPolyPolygon->aXPolyList.size();
    1345           0 :     Rectangle aRect;
    1346             : 
    1347           0 :     for ( size_t n = 0; n < nXPoly; n++ )
    1348             :     {
    1349           0 :         const XPolygon* pXPoly = pImpXPolyPolygon->aXPolyList[ n ];
    1350           0 :         aRect.Union( pXPoly->GetBoundRect() );
    1351             :     }
    1352             : 
    1353           0 :     return aRect;
    1354             : }
    1355             : 
    1356             : 
    1357             : /*************************************************************************
    1358             : |*
    1359             : |*    XPolyPolygon::operator[]()
    1360             : |*
    1361             : *************************************************************************/
    1362             : 
    1363           0 : XPolygon& XPolyPolygon::operator[]( sal_uInt16 nPos )
    1364             : {
    1365           0 :     CheckReference();
    1366           0 :     return *( pImpXPolyPolygon->aXPolyList[ nPos ] );
    1367             : }
    1368             : 
    1369             : /*************************************************************************
    1370             : |*
    1371             : |*    XPolyPolygon::operator=()
    1372             : |*
    1373             : *************************************************************************/
    1374             : 
    1375           0 : XPolyPolygon& XPolyPolygon::operator=( const XPolyPolygon& rXPolyPoly )
    1376             : {
    1377           0 :     rXPolyPoly.pImpXPolyPolygon->nRefCount++;
    1378             : 
    1379           0 :     if( pImpXPolyPolygon->nRefCount > 1 )
    1380           0 :         pImpXPolyPolygon->nRefCount--;
    1381             :     else
    1382           0 :         delete pImpXPolyPolygon;
    1383             : 
    1384           0 :     pImpXPolyPolygon = rXPolyPoly.pImpXPolyPolygon;
    1385           0 :     return *this;
    1386             : }
    1387             : 
    1388             : 
    1389             : /*************************************************************************
    1390             : |*
    1391             : |*    XPolyPolygon::operator==()
    1392             : |*
    1393             : *************************************************************************/
    1394             : 
    1395           0 : sal_Bool XPolyPolygon::operator==( const XPolyPolygon& rXPolyPoly ) const
    1396             : {
    1397           0 :     if (pImpXPolyPolygon==rXPolyPoly.pImpXPolyPolygon) return sal_True;
    1398           0 :     return *pImpXPolyPolygon == *rXPolyPoly.pImpXPolyPolygon;
    1399             : }
    1400             : 
    1401             : 
    1402             : /*************************************************************************
    1403             : |*
    1404             : |*    XPolyPolygon::operator!=()
    1405             : |*
    1406             : *************************************************************************/
    1407             : 
    1408           0 : sal_Bool XPolyPolygon::operator!=( const XPolyPolygon& rXPolyPoly ) const
    1409             : {
    1410           0 :     if (pImpXPolyPolygon==rXPolyPoly.pImpXPolyPolygon) return sal_False;
    1411           0 :     return *pImpXPolyPolygon != *rXPolyPoly.pImpXPolyPolygon;
    1412             : }
    1413             : 
    1414             : /*************************************************************************
    1415             : |*
    1416             : |*    XPolygon::Distort()
    1417             : |*
    1418             : |*    XPolygon verzerren, indem die Koordinaten relativ zu einem
    1419             : |*    Referenzrechteck in ein beliebiges Viereck skaliert werden
    1420             : |*    Zuordnung der Viereck-Punkte im Polygon zum Referenzrechteck:
    1421             : |*    0: links oben      0----1
    1422             : |*    1: rechts oben     |    |
    1423             : |*    2: rechts unten    3----2
    1424             : |*    3: links unten
    1425             : |*
    1426             : *************************************************************************/
    1427             : 
    1428           0 : void XPolyPolygon::Distort(const Rectangle& rRefRect,
    1429             :                            const XPolygon& rDistortedRect)
    1430             : {
    1431           0 :     CheckReference();
    1432             : 
    1433           0 :     for (size_t i = 0; i < Count(); i++)
    1434           0 :         pImpXPolyPolygon->aXPolyList[ i ]->Distort(rRefRect, rDistortedRect);
    1435           0 : }
    1436             : 
    1437           0 : basegfx::B2DPolyPolygon XPolyPolygon::getB2DPolyPolygon() const
    1438             : {
    1439           0 :     basegfx::B2DPolyPolygon aRetval;
    1440             : 
    1441           0 :     for(sal_uInt16 a(0L); a < Count(); a++)
    1442             :     {
    1443           0 :         const XPolygon& rPoly = (*this)[a];
    1444           0 :         aRetval.append(rPoly.getB2DPolygon());
    1445             :     }
    1446             : 
    1447           0 :     return aRetval;
    1448             : }
    1449             : 
    1450           0 : XPolyPolygon::XPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon)
    1451             : {
    1452             :     DBG_CTOR(XPolyPolygon,NULL);
    1453           0 :     pImpXPolyPolygon = new ImpXPolyPolygon();
    1454             : 
    1455           0 :     for(sal_uInt32 a(0L); a < rPolyPolygon.count(); a++)
    1456             :     {
    1457           0 :         basegfx::B2DPolygon aCandidate = rPolyPolygon.getB2DPolygon(a);
    1458           0 :         XPolygon aNewPoly(aCandidate);
    1459           0 :         Insert(aNewPoly);
    1460           0 :     }
    1461           0 : }
    1462             : 
    1463             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10