LCOV - code coverage report
Current view: top level - libreoffice/basegfx/source/polygon - b2dpolygon.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 478 643 74.3 %
Date: 2012-12-27 Functions: 105 123 85.4 %
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/diagnose.h>
      21             : #include <basegfx/polygon/b2dpolygon.hxx>
      22             : #include <basegfx/point/b2dpoint.hxx>
      23             : #include <basegfx/vector/b2dvector.hxx>
      24             : #include <basegfx/matrix/b2dhommatrix.hxx>
      25             : #include <basegfx/curve/b2dcubicbezier.hxx>
      26             : #include <rtl/instance.hxx>
      27             : #include <basegfx/polygon/b2dpolygontools.hxx>
      28             : #include <boost/scoped_ptr.hpp>
      29             : #include <vector>
      30             : #include <algorithm>
      31             : 
      32             : //////////////////////////////////////////////////////////////////////////////
      33             : 
      34     1270197 : struct CoordinateData2D : public basegfx::B2DPoint
      35             : {
      36             : public:
      37           0 :     CoordinateData2D() {}
      38             : 
      39      216410 :     explicit CoordinateData2D(const basegfx::B2DPoint& rData)
      40      216410 :     :   B2DPoint(rData)
      41      216410 :     {}
      42             : 
      43      160506 :     CoordinateData2D& operator=(const basegfx::B2DPoint& rData)
      44             :     {
      45      160506 :         B2DPoint::operator=(rData);
      46      160506 :         return *this;
      47             :     }
      48             : 
      49        9106 :     void transform(const basegfx::B2DHomMatrix& rMatrix)
      50             :     {
      51        9106 :         *this *= rMatrix;
      52        9106 :     }
      53             : };
      54             : 
      55             : //////////////////////////////////////////////////////////////////////////////
      56             : 
      57       94570 : class CoordinateDataArray2D
      58             : {
      59             :     typedef ::std::vector< CoordinateData2D > CoordinateData2DVector;
      60             : 
      61             :     CoordinateData2DVector                          maVector;
      62             : 
      63             : public:
      64          26 :     explicit CoordinateDataArray2D(sal_uInt32 nCount)
      65          26 :     :   maVector(nCount)
      66             :     {
      67          26 :     }
      68             : 
      69       94712 :     explicit CoordinateDataArray2D(const CoordinateDataArray2D& rOriginal)
      70       94712 :     :   maVector(rOriginal.maVector)
      71             :     {
      72       94712 :     }
      73             : 
      74           0 :     CoordinateDataArray2D(const CoordinateDataArray2D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
      75           0 :     :   maVector(rOriginal.maVector.begin() + nIndex, rOriginal.maVector.begin() + (nIndex + nCount))
      76             :     {
      77           0 :     }
      78             : 
      79      288283 :     sal_uInt32 count() const
      80             :     {
      81      288283 :         return maVector.size();
      82             :     }
      83             : 
      84         712 :     bool operator==(const CoordinateDataArray2D& rCandidate) const
      85             :     {
      86         712 :         return (maVector == rCandidate.maVector);
      87             :     }
      88             : 
      89     1296832 :     const basegfx::B2DPoint& getCoordinate(sal_uInt32 nIndex) const
      90             :     {
      91     1296832 :         return maVector[nIndex];
      92             :     }
      93             : 
      94      160506 :     void setCoordinate(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue)
      95             :     {
      96      160506 :         maVector[nIndex] = rValue;
      97      160506 :     }
      98             : 
      99          15 :     void reserve(sal_uInt32 nCount)
     100             :     {
     101          15 :         maVector.reserve(nCount);
     102          15 :     }
     103             : 
     104      162568 :     void append(const CoordinateData2D& rValue)
     105             :     {
     106      162568 :         maVector.push_back(rValue);
     107      162568 :     }
     108             : 
     109       53842 :     void insert(sal_uInt32 nIndex, const CoordinateData2D& rValue, sal_uInt32 nCount)
     110             :     {
     111       53842 :         if(nCount)
     112             :         {
     113             :             // add nCount copies of rValue
     114       53842 :             CoordinateData2DVector::iterator aIndex(maVector.begin());
     115       53842 :             aIndex += nIndex;
     116       53842 :             maVector.insert(aIndex, nCount, rValue);
     117             :         }
     118       53842 :     }
     119             : 
     120           0 :     void insert(sal_uInt32 nIndex, const CoordinateDataArray2D& rSource)
     121             :     {
     122           0 :         const sal_uInt32 nCount(rSource.maVector.size());
     123             : 
     124           0 :         if(nCount)
     125             :         {
     126             :             // insert data
     127           0 :             CoordinateData2DVector::iterator aIndex(maVector.begin());
     128           0 :             aIndex += nIndex;
     129           0 :             CoordinateData2DVector::const_iterator aStart(rSource.maVector.begin());
     130           0 :             CoordinateData2DVector::const_iterator aEnd(rSource.maVector.end());
     131           0 :             maVector.insert(aIndex, aStart, aEnd);
     132             :         }
     133           0 :     }
     134             : 
     135        1222 :     void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
     136             :     {
     137        1222 :         if(nCount)
     138             :         {
     139             :             // remove point data
     140        1222 :             CoordinateData2DVector::iterator aStart(maVector.begin());
     141        1222 :             aStart += nIndex;
     142        1222 :             const CoordinateData2DVector::iterator aEnd(aStart + nCount);
     143        1222 :             maVector.erase(aStart, aEnd);
     144             :         }
     145        1222 :     }
     146             : 
     147         587 :     void flip(bool bIsClosed)
     148             :     {
     149         587 :         if(maVector.size() > 1)
     150             :         {
     151             :             // to keep the same point at index 0, just flip all points except the
     152             :             // first one when closed
     153         587 :             const sal_uInt32 nHalfSize(bIsClosed ? (maVector.size() - 1) >> 1 : maVector.size() >> 1);
     154         587 :             CoordinateData2DVector::iterator aStart(bIsClosed ? maVector.begin() + 1 : maVector.begin());
     155         587 :             CoordinateData2DVector::iterator aEnd(maVector.end() - 1);
     156             : 
     157        1558 :             for(sal_uInt32 a(0); a < nHalfSize; a++)
     158             :             {
     159         971 :                 ::std::swap(*aStart, *aEnd);
     160         971 :                 ++aStart;
     161         971 :                 --aEnd;
     162             :             }
     163             :         }
     164         587 :     }
     165             : 
     166          17 :     void removeDoublePointsAtBeginEnd()
     167             :     {
     168             :         // remove from end as long as there are at least two points
     169             :         // and begin/end are equal
     170          37 :         while((maVector.size() > 1) && (maVector[0] == maVector[maVector.size() - 1]))
     171             :         {
     172           3 :             maVector.pop_back();
     173             :         }
     174          17 :     }
     175             : 
     176          17 :     void removeDoublePointsWholeTrack()
     177             :     {
     178          17 :         sal_uInt32 nIndex(0);
     179             : 
     180             :         // test as long as there are at least two points and as long as the index
     181             :         // is smaller or equal second last point
     182         107 :         while((maVector.size() > 1) && (nIndex <= maVector.size() - 2))
     183             :         {
     184          73 :             if(maVector[nIndex] == maVector[nIndex + 1])
     185             :             {
     186             :                 // if next is same as index, delete next
     187          14 :                 maVector.erase(maVector.begin() + (nIndex + 1));
     188             :             }
     189             :             else
     190             :             {
     191             :                 // if different, step forward
     192          59 :                 nIndex++;
     193             :             }
     194             :         }
     195          17 :     }
     196             : 
     197        2975 :     void transform(const basegfx::B2DHomMatrix& rMatrix)
     198             :     {
     199        2975 :         CoordinateData2DVector::iterator aStart(maVector.begin());
     200        2975 :         CoordinateData2DVector::iterator aEnd(maVector.end());
     201             : 
     202       12081 :         for(; aStart != aEnd; ++aStart)
     203             :         {
     204        9106 :             aStart->transform(rMatrix);
     205             :         }
     206        2975 :     }
     207             : 
     208             :     const basegfx::B2DPoint* begin() const
     209             :     {
     210             :         if(maVector.empty())
     211             :             return 0;
     212             :         else
     213             :             return &maVector.front();
     214             :     }
     215             : 
     216             :     const basegfx::B2DPoint* end() const
     217             :     {
     218             :         if(maVector.empty())
     219             :             return 0;
     220             :         else
     221             :             return (&maVector.back())+1;
     222             :     }
     223             : 
     224             :     basegfx::B2DPoint* begin()
     225             :     {
     226             :         if(maVector.empty())
     227             :             return 0;
     228             :         else
     229             :             return &maVector.front();
     230             :     }
     231             : 
     232             :     basegfx::B2DPoint* end()
     233             :     {
     234             :         if(maVector.empty())
     235             :             return 0;
     236             :         else
     237             :             return (&maVector.back())+1;
     238             :     }
     239             : };
     240             : 
     241             : //////////////////////////////////////////////////////////////////////////////
     242             : 
     243       22609 : class ControlVectorPair2D
     244             : {
     245             :     basegfx::B2DVector                          maPrevVector;
     246             :     basegfx::B2DVector                          maNextVector;
     247             : 
     248             : public:
     249        3432 :     explicit ControlVectorPair2D() {}
     250             : 
     251       18540 :     const basegfx::B2DVector& getPrevVector() const
     252             :     {
     253       18540 :         return maPrevVector;
     254             :     }
     255             : 
     256        4582 :     void setPrevVector(const basegfx::B2DVector& rValue)
     257             :     {
     258        4582 :         if(rValue != maPrevVector)
     259        4341 :             maPrevVector = rValue;
     260        4582 :     }
     261             : 
     262       17964 :     const basegfx::B2DVector& getNextVector() const
     263             :     {
     264       17964 :         return maNextVector;
     265             :     }
     266             : 
     267        4606 :     void setNextVector(const basegfx::B2DVector& rValue)
     268             :     {
     269        4606 :         if(rValue != maNextVector)
     270        4358 :             maNextVector = rValue;
     271        4606 :     }
     272             : 
     273         117 :     bool operator==(const ControlVectorPair2D& rData) const
     274             :     {
     275         117 :         return (maPrevVector == rData.getPrevVector() && maNextVector == rData.getNextVector());
     276             :     }
     277             : 
     278           0 :     void flip()
     279             :     {
     280           0 :         ::std::swap(maPrevVector, maNextVector);
     281           0 :     }
     282             : };
     283             : 
     284             : //////////////////////////////////////////////////////////////////////////////
     285             : 
     286         337 : class ControlVectorArray2D
     287             : {
     288             :     typedef ::std::vector< ControlVectorPair2D > ControlVectorPair2DVector;
     289             : 
     290             :     ControlVectorPair2DVector                           maVector;
     291             :     sal_uInt32                                          mnUsedVectors;
     292             : 
     293             : public:
     294         229 :     explicit ControlVectorArray2D(sal_uInt32 nCount)
     295             :     :   maVector(nCount),
     296         229 :         mnUsedVectors(0)
     297         229 :     {}
     298             : 
     299           0 :     ControlVectorArray2D(const ControlVectorArray2D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
     300             :     :   maVector(),
     301           0 :         mnUsedVectors(0)
     302             :     {
     303           0 :         ControlVectorPair2DVector::const_iterator aStart(rOriginal.maVector.begin());
     304           0 :         aStart += nIndex;
     305           0 :         ControlVectorPair2DVector::const_iterator aEnd(aStart);
     306           0 :         aEnd += nCount;
     307           0 :         maVector.reserve(nCount);
     308             : 
     309           0 :         for(; aStart != aEnd; ++aStart)
     310             :         {
     311           0 :             if(!aStart->getPrevVector().equalZero())
     312           0 :                 mnUsedVectors++;
     313             : 
     314           0 :             if(!aStart->getNextVector().equalZero())
     315           0 :                 mnUsedVectors++;
     316             : 
     317           0 :             maVector.push_back(*aStart);
     318             :         }
     319           0 :     }
     320             : 
     321             :     sal_uInt32 count() const
     322             :     {
     323             :         return maVector.size();
     324             :     }
     325             : 
     326           9 :     bool operator==(const ControlVectorArray2D& rCandidate) const
     327             :     {
     328           9 :         return (maVector == rCandidate.maVector);
     329             :     }
     330             : 
     331       20146 :     bool isUsed() const
     332             :     {
     333       20146 :         return (0 != mnUsedVectors);
     334             :     }
     335             : 
     336       10585 :     const basegfx::B2DVector& getPrevVector(sal_uInt32 nIndex) const
     337             :     {
     338       10585 :         return maVector[nIndex].getPrevVector();
     339             :     }
     340             : 
     341        4642 :     void setPrevVector(sal_uInt32 nIndex, const basegfx::B2DVector& rValue)
     342             :     {
     343        4642 :         bool bWasUsed(mnUsedVectors && !maVector[nIndex].getPrevVector().equalZero());
     344        4642 :         bool bIsUsed(!rValue.equalZero());
     345             : 
     346        4642 :         if(bWasUsed)
     347             :         {
     348        2345 :             if(bIsUsed)
     349             :             {
     350        2345 :                 maVector[nIndex].setPrevVector(rValue);
     351             :             }
     352             :             else
     353             :             {
     354           0 :                 maVector[nIndex].setPrevVector(basegfx::B2DVector::getEmptyVector());
     355           0 :                 mnUsedVectors--;
     356             :             }
     357             :         }
     358             :         else
     359             :         {
     360        2297 :             if(bIsUsed)
     361             :             {
     362        2237 :                 maVector[nIndex].setPrevVector(rValue);
     363        2237 :                 mnUsedVectors++;
     364             :             }
     365             :         }
     366        4642 :     }
     367             : 
     368       10264 :     const basegfx::B2DVector& getNextVector(sal_uInt32 nIndex) const
     369             :     {
     370       10264 :         return maVector[nIndex].getNextVector();
     371             :     }
     372             : 
     373        4614 :     void setNextVector(sal_uInt32 nIndex, const basegfx::B2DVector& rValue)
     374             :     {
     375        4614 :         bool bWasUsed(mnUsedVectors && !maVector[nIndex].getNextVector().equalZero());
     376        4614 :         bool bIsUsed(!rValue.equalZero());
     377             : 
     378        4614 :         if(bWasUsed)
     379             :         {
     380        2401 :             if(bIsUsed)
     381             :             {
     382        2401 :                 maVector[nIndex].setNextVector(rValue);
     383             :             }
     384             :             else
     385             :             {
     386           0 :                 maVector[nIndex].setNextVector(basegfx::B2DVector::getEmptyVector());
     387           0 :                 mnUsedVectors--;
     388             :             }
     389             :         }
     390             :         else
     391             :         {
     392        2213 :             if(bIsUsed)
     393             :             {
     394        2205 :                 maVector[nIndex].setNextVector(rValue);
     395        2205 :                 mnUsedVectors++;
     396             :             }
     397             :         }
     398        4614 :     }
     399             : 
     400         753 :     void append(const ControlVectorPair2D& rValue)
     401             :     {
     402         753 :         maVector.push_back(rValue);
     403             : 
     404         753 :         if(!rValue.getPrevVector().equalZero())
     405           0 :             mnUsedVectors += 1;
     406             : 
     407         753 :         if(!rValue.getNextVector().equalZero())
     408           0 :             mnUsedVectors += 1;
     409         753 :     }
     410             : 
     411        2213 :     void insert(sal_uInt32 nIndex, const ControlVectorPair2D& rValue, sal_uInt32 nCount)
     412             :     {
     413        2213 :         if(nCount)
     414             :         {
     415             :             // add nCount copies of rValue
     416        2213 :             ControlVectorPair2DVector::iterator aIndex(maVector.begin());
     417        2213 :             aIndex += nIndex;
     418        2213 :             maVector.insert(aIndex, nCount, rValue);
     419             : 
     420        2213 :             if(!rValue.getPrevVector().equalZero())
     421           0 :                 mnUsedVectors += nCount;
     422             : 
     423        2213 :             if(!rValue.getNextVector().equalZero())
     424           0 :                 mnUsedVectors += nCount;
     425             :         }
     426        2213 :     }
     427             : 
     428           0 :     void insert(sal_uInt32 nIndex, const ControlVectorArray2D& rSource)
     429             :     {
     430           0 :         const sal_uInt32 nCount(rSource.maVector.size());
     431             : 
     432           0 :         if(nCount)
     433             :         {
     434             :             // insert data
     435           0 :             ControlVectorPair2DVector::iterator aIndex(maVector.begin());
     436           0 :             aIndex += nIndex;
     437           0 :             ControlVectorPair2DVector::const_iterator aStart(rSource.maVector.begin());
     438           0 :             ControlVectorPair2DVector::const_iterator aEnd(rSource.maVector.end());
     439           0 :             maVector.insert(aIndex, aStart, aEnd);
     440             : 
     441           0 :             for(; aStart != aEnd; ++aStart)
     442             :             {
     443           0 :                 if(!aStart->getPrevVector().equalZero())
     444           0 :                     mnUsedVectors++;
     445             : 
     446           0 :                 if(!aStart->getNextVector().equalZero())
     447           0 :                     mnUsedVectors++;
     448             :             }
     449             :         }
     450           0 :     }
     451             : 
     452         213 :     void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
     453             :     {
     454         213 :         if(nCount)
     455             :         {
     456         213 :             const ControlVectorPair2DVector::iterator aDeleteStart(maVector.begin() + nIndex);
     457         213 :             const ControlVectorPair2DVector::iterator aDeleteEnd(aDeleteStart + nCount);
     458         213 :             ControlVectorPair2DVector::const_iterator aStart(aDeleteStart);
     459             : 
     460         444 :             for(; mnUsedVectors && aStart != aDeleteEnd; ++aStart)
     461             :             {
     462         231 :                 if(!aStart->getPrevVector().equalZero())
     463          85 :                     mnUsedVectors--;
     464             : 
     465         231 :                 if(mnUsedVectors && !aStart->getNextVector().equalZero())
     466           0 :                     mnUsedVectors--;
     467             :             }
     468             : 
     469             :             // remove point data
     470         213 :             maVector.erase(aDeleteStart, aDeleteEnd);
     471             :         }
     472         213 :     }
     473             : 
     474           0 :     void flip(bool bIsClosed)
     475             :     {
     476           0 :         if(maVector.size() > 1)
     477             :         {
     478             :             // to keep the same point at index 0, just flip all points except the
     479             :             // first one when closed
     480           0 :             const sal_uInt32 nHalfSize(bIsClosed ? (maVector.size() - 1) >> 1 : maVector.size() >> 1);
     481           0 :             ControlVectorPair2DVector::iterator aStart(bIsClosed ? maVector.begin() + 1 : maVector.begin());
     482           0 :             ControlVectorPair2DVector::iterator aEnd(maVector.end() - 1);
     483             : 
     484           0 :             for(sal_uInt32 a(0); a < nHalfSize; a++)
     485             :             {
     486             :                 // swap Prev and Next
     487           0 :                 aStart->flip();
     488           0 :                 aEnd->flip();
     489             : 
     490             :                 // swap entries
     491           0 :                 ::std::swap(*aStart, *aEnd);
     492             : 
     493           0 :                 ++aStart;
     494           0 :                 --aEnd;
     495             :             }
     496             : 
     497           0 :             if(aStart == aEnd)
     498             :             {
     499             :                 // swap Prev and Next at middle element (if exists)
     500           0 :                 aStart->flip();
     501             :             }
     502             : 
     503           0 :             if(bIsClosed)
     504             :             {
     505             :                 // swap Prev and Next at start element
     506           0 :                 maVector.begin()->flip();
     507             :             }
     508             :         }
     509           0 :     }
     510             : };
     511             : 
     512             : //////////////////////////////////////////////////////////////////////////////
     513             : 
     514       82916 : class ImplBufferedData
     515             : {
     516             : private:
     517             :     // Possibility to hold the last subdivision
     518             :     boost::scoped_ptr< basegfx::B2DPolygon >        mpDefaultSubdivision;
     519             : 
     520             :     // Possibility to hold the last B2DRange calculation
     521             :     boost::scoped_ptr< basegfx::B2DRange >          mpB2DRange;
     522             : 
     523             : public:
     524       82965 :     ImplBufferedData()
     525             :     :   mpDefaultSubdivision(),
     526       82965 :         mpB2DRange()
     527       82965 :     {}
     528             : 
     529           0 :     const basegfx::B2DPolygon& getDefaultAdaptiveSubdivision(const basegfx::B2DPolygon& rSource) const
     530             :     {
     531           0 :         if(!mpDefaultSubdivision)
     532             :         {
     533           0 :             const_cast< ImplBufferedData* >(this)->mpDefaultSubdivision.reset(new basegfx::B2DPolygon(basegfx::tools::adaptiveSubdivideByCount(rSource, 9)));
     534             :         }
     535             : 
     536           0 :         return *mpDefaultSubdivision;
     537             :     }
     538             : 
     539       83226 :     const basegfx::B2DRange& getB2DRange(const basegfx::B2DPolygon& rSource) const
     540             :     {
     541       83226 :         if(!mpB2DRange)
     542             :         {
     543       82965 :             basegfx::B2DRange aNewRange;
     544       82965 :             const sal_uInt32 nPointCount(rSource.count());
     545             : 
     546       82965 :             if(nPointCount)
     547             :             {
     548      419447 :                 for(sal_uInt32 a(0); a < nPointCount; a++)
     549             :                 {
     550      336482 :                     aNewRange.expand(rSource.getB2DPoint(a));
     551             :                 }
     552             : 
     553       82965 :                 if(rSource.areControlPointsUsed())
     554             :                 {
     555          35 :                     const sal_uInt32 nEdgeCount(rSource.isClosed() ? nPointCount : nPointCount - 1);
     556             : 
     557          35 :                     if(nEdgeCount)
     558             :                     {
     559          35 :                         basegfx::B2DCubicBezier aEdge;
     560          35 :                         aEdge.setStartPoint(rSource.getB2DPoint(0));
     561             : 
     562         470 :                         for(sal_uInt32 b(0); b < nEdgeCount; b++)
     563             :                         {
     564         435 :                             const sal_uInt32 nNextIndex((b + 1) % nPointCount);
     565         435 :                             aEdge.setControlPointA(rSource.getNextControlPoint(b));
     566         435 :                             aEdge.setControlPointB(rSource.getPrevControlPoint(nNextIndex));
     567         435 :                             aEdge.setEndPoint(rSource.getB2DPoint(nNextIndex));
     568             : 
     569         435 :                             if(aEdge.isBezier())
     570             :                             {
     571         391 :                                 const basegfx::B2DRange aBezierRangeWithControlPoints(aEdge.getRange());
     572             : 
     573         391 :                                 if(!aNewRange.isInside(aBezierRangeWithControlPoints))
     574             :                                 {
     575             :                                     // the range with control points of the current edge is not completely
     576             :                                     // inside the current range without control points. Expand current range by
     577             :                                     // subdividing the bezier segment.
     578             :                                     // Ideal here is a subdivision at the extreme values, so use
     579             :                                     // getAllExtremumPositions to get all extremas in one run
     580         102 :                                     ::std::vector< double > aExtremas;
     581             : 
     582         102 :                                     aExtremas.reserve(4);
     583         102 :                                     aEdge.getAllExtremumPositions(aExtremas);
     584             : 
     585         102 :                                     const sal_uInt32 nExtremaCount(aExtremas.size());
     586             : 
     587         237 :                                     for(sal_uInt32 c(0); c < nExtremaCount; c++)
     588             :                                     {
     589         135 :                                         aNewRange.expand(aEdge.interpolatePoint(aExtremas[c]));
     590         102 :                                     }
     591             :                                 }
     592             :                             }
     593             : 
     594             :                             // prepare next edge
     595         435 :                             aEdge.setStartPoint(aEdge.getEndPoint());
     596          35 :                         }
     597             :                     }
     598             :                 }
     599             :             }
     600             : 
     601       82965 :             const_cast< ImplBufferedData* >(this)->mpB2DRange.reset(new basegfx::B2DRange(aNewRange));
     602             :         }
     603             : 
     604       83226 :         return *mpB2DRange;
     605             :     }
     606             : };
     607             : 
     608             : //////////////////////////////////////////////////////////////////////////////
     609             : 
     610       94570 : class ImplB2DPolygon
     611             : {
     612             : private:
     613             :     // The point vector. This vector exists always and defines the
     614             :     // count of members.
     615             :     CoordinateDataArray2D                           maPoints;
     616             : 
     617             :     // The control point vectors. This vectors are created on demand
     618             :     // and may be zero.
     619             :     boost::scoped_ptr< ControlVectorArray2D >       mpControlVector;
     620             : 
     621             :     // buffered data for e.g. default subdivision and range
     622             :     boost::scoped_ptr< ImplBufferedData >           mpBufferedData;
     623             : 
     624             :     // flag which decides if this polygon is opened or closed
     625             :     bool                                            mbIsClosed;
     626             : 
     627             : public:
     628           0 :     const basegfx::B2DPolygon& getDefaultAdaptiveSubdivision(const basegfx::B2DPolygon& rSource) const
     629             :     {
     630           0 :         if(!mpControlVector || !mpControlVector->isUsed())
     631             :         {
     632           0 :             return rSource;
     633             :         }
     634             : 
     635           0 :         if(!mpBufferedData)
     636             :         {
     637           0 :             const_cast< ImplB2DPolygon* >(this)->mpBufferedData.reset(new ImplBufferedData);
     638             :         }
     639             : 
     640           0 :         return mpBufferedData->getDefaultAdaptiveSubdivision(rSource);
     641             :     }
     642             : 
     643       83226 :     const basegfx::B2DRange& getB2DRange(const basegfx::B2DPolygon& rSource) const
     644             :     {
     645       83226 :         if(!mpBufferedData)
     646             :         {
     647       82965 :             const_cast< ImplB2DPolygon* >(this)->mpBufferedData.reset(new ImplBufferedData);
     648             :         }
     649             : 
     650       83226 :         return mpBufferedData->getB2DRange(rSource);
     651             :     }
     652             : 
     653          26 :     ImplB2DPolygon()
     654             :     :   maPoints(0),
     655             :         mpControlVector(),
     656             :         mpBufferedData(),
     657          26 :         mbIsClosed(false)
     658          26 :     {}
     659             : 
     660       94712 :     ImplB2DPolygon(const ImplB2DPolygon& rToBeCopied)
     661             :     :   maPoints(rToBeCopied.maPoints),
     662             :         mpControlVector(),
     663             :         mpBufferedData(),
     664       94712 :         mbIsClosed(rToBeCopied.mbIsClosed)
     665             :     {
     666             :         // complete initialization using copy
     667       94712 :         if(rToBeCopied.mpControlVector && rToBeCopied.mpControlVector->isUsed())
     668             :         {
     669          59 :             mpControlVector.reset( new ControlVectorArray2D(*rToBeCopied.mpControlVector) );
     670             :         }
     671       94712 :     }
     672             : 
     673           0 :     ImplB2DPolygon(const ImplB2DPolygon& rToBeCopied, sal_uInt32 nIndex, sal_uInt32 nCount)
     674             :     :   maPoints(rToBeCopied.maPoints, nIndex, nCount),
     675             :         mpControlVector(),
     676             :         mpBufferedData(),
     677           0 :         mbIsClosed(rToBeCopied.mbIsClosed)
     678             :     {
     679             :         // complete initialization using partly copy
     680           0 :         if(rToBeCopied.mpControlVector && rToBeCopied.mpControlVector->isUsed())
     681             :         {
     682           0 :             mpControlVector.reset( new ControlVectorArray2D(*rToBeCopied.mpControlVector, nIndex, nCount) );
     683             : 
     684           0 :             if(!mpControlVector->isUsed())
     685           0 :                 mpControlVector.reset();
     686             :         }
     687           0 :     }
     688             : 
     689             :     ImplB2DPolygon& operator=( const ImplB2DPolygon& rToBeCopied )
     690             :     {
     691             :         maPoints = rToBeCopied.maPoints;
     692             :         mpControlVector.reset();
     693             :         mpBufferedData.reset();
     694             :         mbIsClosed = rToBeCopied.mbIsClosed;
     695             : 
     696             :         // complete initialization using copy
     697             :         if(rToBeCopied.mpControlVector && rToBeCopied.mpControlVector->isUsed())
     698             :             mpControlVector.reset( new ControlVectorArray2D(*rToBeCopied.mpControlVector) );
     699             : 
     700             :         return *this;
     701             :     }
     702             : 
     703      277655 :     sal_uInt32 count() const
     704             :     {
     705      277655 :         return maPoints.count();
     706             :     }
     707             : 
     708      100876 :     bool isClosed() const
     709             :     {
     710      100876 :         return mbIsClosed;
     711             :     }
     712             : 
     713       82450 :     void setClosed(bool bNew)
     714             :     {
     715       82450 :         if(bNew != mbIsClosed)
     716             :         {
     717       82450 :             mpBufferedData.reset();
     718       82450 :             mbIsClosed = bNew;
     719             :         }
     720       82450 :     }
     721             : 
     722         814 :     bool operator==(const ImplB2DPolygon& rCandidate) const
     723             :     {
     724         814 :         if(mbIsClosed == rCandidate.mbIsClosed)
     725             :         {
     726         712 :             if(maPoints == rCandidate.maPoints)
     727             :             {
     728         228 :                 bool bControlVectorsAreEqual(true);
     729             : 
     730         228 :                 if(mpControlVector)
     731             :                 {
     732           9 :                     if(rCandidate.mpControlVector)
     733             :                     {
     734           9 :                         bControlVectorsAreEqual = ((*mpControlVector) == (*rCandidate.mpControlVector));
     735             :                     }
     736             :                     else
     737             :                     {
     738             :                         // candidate has no control vector, so it's assumed all unused.
     739           0 :                         bControlVectorsAreEqual = !mpControlVector->isUsed();
     740             :                     }
     741             :                 }
     742             :                 else
     743             :                 {
     744         219 :                     if(rCandidate.mpControlVector)
     745             :                     {
     746             :                         // we have no control vector, so it's assumed all unused.
     747           0 :                         bControlVectorsAreEqual = !rCandidate.mpControlVector->isUsed();
     748             :                     }
     749             :                 }
     750             : 
     751         228 :                 if(bControlVectorsAreEqual)
     752             :                 {
     753         228 :                     return true;
     754             :                 }
     755             :             }
     756             :         }
     757             : 
     758         586 :         return false;
     759             :     }
     760             : 
     761     1286446 :     const basegfx::B2DPoint& getPoint(sal_uInt32 nIndex) const
     762             :     {
     763     1286446 :         return maPoints.getCoordinate(nIndex);
     764             :     }
     765             : 
     766      157132 :     void setPoint(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue)
     767             :     {
     768      157132 :         mpBufferedData.reset();
     769      157132 :         maPoints.setCoordinate(nIndex, rValue);
     770      157132 :     }
     771             : 
     772          15 :     void reserve(sal_uInt32 nCount)
     773             :     {
     774          15 :         maPoints.reserve(nCount);
     775          15 :     }
     776             : 
     777      162568 :     void append(const basegfx::B2DPoint& rPoint)
     778             :     {
     779      162568 :         mpBufferedData.reset(); // TODO: is this needed?
     780      162568 :         const CoordinateData2D aCoordinate(rPoint);
     781      162568 :         maPoints.append(aCoordinate);
     782             : 
     783      162568 :         if(mpControlVector)
     784             :         {
     785         753 :             const ControlVectorPair2D aVectorPair;
     786         753 :             mpControlVector->append(aVectorPair);
     787      162568 :         }
     788      162568 :     }
     789             : 
     790       53842 :     void insert(sal_uInt32 nIndex, const basegfx::B2DPoint& rPoint, sal_uInt32 nCount)
     791             :     {
     792       53842 :         if(nCount)
     793             :         {
     794       53842 :             mpBufferedData.reset();
     795       53842 :             CoordinateData2D aCoordinate(rPoint);
     796       53842 :             maPoints.insert(nIndex, aCoordinate, nCount);
     797             : 
     798       53842 :             if(mpControlVector)
     799             :             {
     800        2213 :                 ControlVectorPair2D aVectorPair;
     801        2213 :                 mpControlVector->insert(nIndex, aVectorPair, nCount);
     802       53842 :             }
     803             :         }
     804       53842 :     }
     805             : 
     806        7212 :     const basegfx::B2DVector& getPrevControlVector(sal_uInt32 nIndex) const
     807             :     {
     808        7212 :         if(mpControlVector)
     809             :         {
     810        7211 :             return mpControlVector->getPrevVector(nIndex);
     811             :         }
     812             :         else
     813             :         {
     814           1 :             return basegfx::B2DVector::getEmptyVector();
     815             :         }
     816             :     }
     817             : 
     818        2310 :     void setPrevControlVector(sal_uInt32 nIndex, const basegfx::B2DVector& rValue)
     819             :     {
     820        2310 :         if(!mpControlVector)
     821             :         {
     822           2 :             if(!rValue.equalZero())
     823             :             {
     824           1 :                 mpBufferedData.reset();
     825           1 :                 mpControlVector.reset( new ControlVectorArray2D(maPoints.count()) );
     826           1 :                 mpControlVector->setPrevVector(nIndex, rValue);
     827             :             }
     828             :         }
     829             :         else
     830             :         {
     831        2308 :             mpBufferedData.reset();
     832        2308 :             mpControlVector->setPrevVector(nIndex, rValue);
     833             : 
     834        2308 :             if(!mpControlVector->isUsed())
     835           0 :                 mpControlVector.reset();
     836             :         }
     837        2310 :     }
     838             : 
     839        6893 :     const basegfx::B2DVector& getNextControlVector(sal_uInt32 nIndex) const
     840             :     {
     841        6893 :         if(mpControlVector)
     842             :         {
     843        6890 :             return mpControlVector->getNextVector(nIndex);
     844             :         }
     845             :         else
     846             :         {
     847           3 :             return basegfx::B2DVector::getEmptyVector();
     848             :         }
     849             :     }
     850             : 
     851        2225 :     void setNextControlVector(sal_uInt32 nIndex, const basegfx::B2DVector& rValue)
     852             :     {
     853        2225 :         if(!mpControlVector)
     854             :         {
     855         228 :             if(!rValue.equalZero())
     856             :             {
     857         228 :                 mpBufferedData.reset();
     858         228 :                 mpControlVector.reset( new ControlVectorArray2D(maPoints.count()) );
     859         228 :                 mpControlVector->setNextVector(nIndex, rValue);
     860             :             }
     861             :         }
     862             :         else
     863             :         {
     864        1997 :             mpBufferedData.reset();
     865        1997 :             mpControlVector->setNextVector(nIndex, rValue);
     866             : 
     867        1997 :             if(!mpControlVector->isUsed())
     868           0 :                 mpControlVector.reset();
     869             :         }
     870        2225 :     }
     871             : 
     872      197909 :     bool areControlPointsUsed() const
     873             :     {
     874      197909 :         return (mpControlVector && mpControlVector->isUsed());
     875             :     }
     876             : 
     877             :     void resetControlVectors(sal_uInt32 nIndex)
     878             :     {
     879             :         setPrevControlVector(nIndex, basegfx::B2DVector::getEmptyVector());
     880             :         setNextControlVector(nIndex, basegfx::B2DVector::getEmptyVector());
     881             :     }
     882             : 
     883           1 :     void resetControlVectors()
     884             :     {
     885           1 :         mpBufferedData.reset();
     886           1 :         mpControlVector.reset();
     887           1 :     }
     888             : 
     889           1 :     void setControlVectors(sal_uInt32 nIndex, const basegfx::B2DVector& rPrev, const basegfx::B2DVector& rNext)
     890             :     {
     891           1 :         setPrevControlVector(nIndex, rPrev);
     892           1 :         setNextControlVector(nIndex, rNext);
     893           1 :     }
     894             : 
     895        2210 :     void appendBezierSegment(const basegfx::B2DVector& rNext, const basegfx::B2DVector& rPrev, const basegfx::B2DPoint& rPoint)
     896             :     {
     897        2210 :         mpBufferedData.reset();
     898        2210 :         const sal_uInt32 nCount(maPoints.count());
     899             : 
     900        2210 :         if(nCount)
     901             :         {
     902        2209 :             setNextControlVector(nCount - 1, rNext);
     903             :         }
     904             : 
     905        2210 :         insert(nCount, rPoint, 1);
     906        2210 :         setPrevControlVector(nCount, rPrev);
     907        2210 :     }
     908             : 
     909           0 :     void insert(sal_uInt32 nIndex, const ImplB2DPolygon& rSource)
     910             :     {
     911           0 :         const sal_uInt32 nCount(rSource.maPoints.count());
     912             : 
     913           0 :         if(nCount)
     914             :         {
     915           0 :             mpBufferedData.reset();
     916             : 
     917           0 :             if(rSource.mpControlVector && rSource.mpControlVector->isUsed() && !mpControlVector)
     918             :             {
     919           0 :                 mpControlVector.reset( new ControlVectorArray2D(maPoints.count()) );
     920             :             }
     921             : 
     922           0 :             maPoints.insert(nIndex, rSource.maPoints);
     923             : 
     924           0 :             if(rSource.mpControlVector)
     925             :             {
     926           0 :                 mpControlVector->insert(nIndex, *rSource.mpControlVector);
     927             : 
     928           0 :                 if(!mpControlVector->isUsed())
     929           0 :                     mpControlVector.reset();
     930             :             }
     931           0 :             else if(mpControlVector)
     932             :             {
     933           0 :                 ControlVectorPair2D aVectorPair;
     934           0 :                 mpControlVector->insert(nIndex, aVectorPair, nCount);
     935             :             }
     936             :         }
     937           0 :     }
     938             : 
     939        1222 :     void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
     940             :     {
     941        1222 :         if(nCount)
     942             :         {
     943        1222 :             mpBufferedData.reset();
     944        1222 :             maPoints.remove(nIndex, nCount);
     945             : 
     946        1222 :             if(mpControlVector)
     947             :             {
     948         213 :                 mpControlVector->remove(nIndex, nCount);
     949             : 
     950         213 :                 if(!mpControlVector->isUsed())
     951           0 :                     mpControlVector.reset();
     952             :             }
     953             :         }
     954        1222 :     }
     955             : 
     956         587 :     void flip()
     957             :     {
     958         587 :         if(maPoints.count() > 1)
     959             :         {
     960         587 :             mpBufferedData.reset();
     961             : 
     962             :             // flip points
     963         587 :             maPoints.flip(mbIsClosed);
     964             : 
     965         587 :             if(mpControlVector)
     966             :             {
     967             :                 // flip control vector
     968           0 :                 mpControlVector->flip(mbIsClosed);
     969             :             }
     970             :         }
     971         587 :     }
     972             : 
     973         514 :     bool hasDoublePoints() const
     974             :     {
     975         514 :         if(mbIsClosed)
     976             :         {
     977             :             // check for same start and end point
     978         416 :             const sal_uInt32 nIndex(maPoints.count() - 1);
     979             : 
     980         416 :             if(maPoints.getCoordinate(0) == maPoints.getCoordinate(nIndex))
     981             :             {
     982           3 :                 if(mpControlVector)
     983             :                 {
     984           0 :                     if(mpControlVector->getNextVector(nIndex).equalZero() && mpControlVector->getPrevVector(0).equalZero())
     985             :                     {
     986           0 :                         return true;
     987             :                     }
     988             :                 }
     989             :                 else
     990             :                 {
     991           3 :                     return true;
     992             :                 }
     993             :             }
     994             :         }
     995             : 
     996             :         // test for range
     997        3575 :         for(sal_uInt32 a(0); a < maPoints.count() - 1; a++)
     998             :         {
     999        3090 :             if(maPoints.getCoordinate(a) == maPoints.getCoordinate(a + 1))
    1000             :             {
    1001          26 :                 if(mpControlVector)
    1002             :                 {
    1003           0 :                     if(mpControlVector->getNextVector(a).equalZero() && mpControlVector->getPrevVector(a + 1).equalZero())
    1004             :                     {
    1005           0 :                         return true;
    1006             :                     }
    1007             :                 }
    1008             :                 else
    1009             :                 {
    1010          26 :                     return true;
    1011             :                 }
    1012             :             }
    1013             :         }
    1014             : 
    1015         485 :         return false;
    1016             :     }
    1017             : 
    1018          17 :     void removeDoublePointsAtBeginEnd()
    1019             :     {
    1020             :         // Only remove DoublePoints at Begin and End when poly is closed
    1021          17 :         if(mbIsClosed)
    1022             :         {
    1023          17 :             mpBufferedData.reset();
    1024             : 
    1025          17 :             if(mpControlVector)
    1026             :             {
    1027             :                 bool bRemove;
    1028             : 
    1029           0 :                 do
    1030             :                 {
    1031           0 :                     bRemove = false;
    1032             : 
    1033           0 :                     if(maPoints.count() > 1)
    1034             :                     {
    1035           0 :                         const sal_uInt32 nIndex(maPoints.count() - 1);
    1036             : 
    1037           0 :                         if(maPoints.getCoordinate(0) == maPoints.getCoordinate(nIndex))
    1038             :                         {
    1039           0 :                             if(mpControlVector)
    1040             :                             {
    1041           0 :                                 if(mpControlVector->getNextVector(nIndex).equalZero() && mpControlVector->getPrevVector(0).equalZero())
    1042             :                                 {
    1043           0 :                                     bRemove = true;
    1044             :                                 }
    1045             :                             }
    1046             :                             else
    1047             :                             {
    1048           0 :                                 bRemove = true;
    1049             :                             }
    1050             :                         }
    1051             :                     }
    1052             : 
    1053           0 :                     if(bRemove)
    1054             :                     {
    1055           0 :                         const sal_uInt32 nIndex(maPoints.count() - 1);
    1056             : 
    1057           0 :                         if(mpControlVector && !mpControlVector->getPrevVector(nIndex).equalZero())
    1058             :                         {
    1059           0 :                             mpControlVector->setPrevVector(0, mpControlVector->getPrevVector(nIndex));
    1060             :                         }
    1061             : 
    1062           0 :                         remove(nIndex, 1);
    1063             :                     }
    1064             :                 }
    1065             :                 while(bRemove);
    1066             :             }
    1067             :             else
    1068             :             {
    1069          17 :                 maPoints.removeDoublePointsAtBeginEnd();
    1070             :             }
    1071             :         }
    1072          17 :     }
    1073             : 
    1074          17 :     void removeDoublePointsWholeTrack()
    1075             :     {
    1076          17 :         mpBufferedData.reset();
    1077             : 
    1078          17 :         if(mpControlVector)
    1079             :         {
    1080           0 :             sal_uInt32 nIndex(0);
    1081             : 
    1082             :             // test as long as there are at least two points and as long as the index
    1083             :             // is smaller or equal second last point
    1084           0 :             while((maPoints.count() > 1) && (nIndex <= maPoints.count() - 2))
    1085             :             {
    1086           0 :                 bool bRemove(maPoints.getCoordinate(nIndex) == maPoints.getCoordinate(nIndex + 1));
    1087             : 
    1088           0 :                 if(bRemove)
    1089             :                 {
    1090           0 :                     if(mpControlVector)
    1091             :                     {
    1092           0 :                         if(!mpControlVector->getNextVector(nIndex).equalZero() || !mpControlVector->getPrevVector(nIndex + 1).equalZero())
    1093             :                         {
    1094           0 :                             bRemove = false;
    1095             :                         }
    1096             :                     }
    1097             :                 }
    1098             : 
    1099           0 :                 if(bRemove)
    1100             :                 {
    1101           0 :                     if(mpControlVector && !mpControlVector->getPrevVector(nIndex).equalZero())
    1102             :                     {
    1103           0 :                         mpControlVector->setPrevVector(nIndex + 1, mpControlVector->getPrevVector(nIndex));
    1104             :                     }
    1105             : 
    1106             :                     // if next is same as index and the control vectors are unused, delete index
    1107           0 :                     remove(nIndex, 1);
    1108             :                 }
    1109             :                 else
    1110             :                 {
    1111             :                     // if different, step forward
    1112           0 :                     nIndex++;
    1113             :                 }
    1114             :             }
    1115             :         }
    1116             :         else
    1117             :         {
    1118          17 :             maPoints.removeDoublePointsWholeTrack();
    1119             :         }
    1120          17 :     }
    1121             : 
    1122        3212 :     void transform(const basegfx::B2DHomMatrix& rMatrix)
    1123             :     {
    1124        3212 :         mpBufferedData.reset();
    1125             : 
    1126        3212 :         if(mpControlVector)
    1127             :         {
    1128        3611 :             for(sal_uInt32 a(0); a < maPoints.count(); a++)
    1129             :             {
    1130        3374 :                 basegfx::B2DPoint aCandidate = maPoints.getCoordinate(a);
    1131             : 
    1132        3374 :                 if(mpControlVector->isUsed())
    1133             :                 {
    1134        3374 :                     const basegfx::B2DVector& rPrevVector(mpControlVector->getPrevVector(a));
    1135        3374 :                     const basegfx::B2DVector& rNextVector(mpControlVector->getNextVector(a));
    1136             : 
    1137        3374 :                     if(!rPrevVector.equalZero())
    1138             :                     {
    1139        2333 :                         basegfx::B2DVector aPrevVector(rMatrix * rPrevVector);
    1140        2333 :                         mpControlVector->setPrevVector(a, aPrevVector);
    1141             :                     }
    1142             : 
    1143        3374 :                     if(!rNextVector.equalZero())
    1144             :                     {
    1145        2389 :                         basegfx::B2DVector aNextVector(rMatrix * rNextVector);
    1146        2389 :                         mpControlVector->setNextVector(a, aNextVector);
    1147             :                     }
    1148             :                 }
    1149             : 
    1150        3374 :                 aCandidate *= rMatrix;
    1151        3374 :                 maPoints.setCoordinate(a, aCandidate);
    1152        3374 :             }
    1153             : 
    1154         237 :             if(!mpControlVector->isUsed())
    1155           0 :                 mpControlVector.reset();
    1156             :         }
    1157             :         else
    1158             :         {
    1159        2975 :             maPoints.transform(rMatrix);
    1160             :         }
    1161        3212 :     }
    1162             : 
    1163             :     const basegfx::B2DPoint* begin() const
    1164             :     {
    1165             :         return maPoints.begin();
    1166             :     }
    1167             : 
    1168             :     const basegfx::B2DPoint* end() const
    1169             :     {
    1170             :         return maPoints.end();
    1171             :     }
    1172             : 
    1173             :     basegfx::B2DPoint* begin()
    1174             :     {
    1175             :        mpBufferedData.reset();
    1176             :        return maPoints.begin();
    1177             :     }
    1178             : 
    1179             :     basegfx::B2DPoint* end()
    1180             :     {
    1181             :         mpBufferedData.reset();
    1182             :         return maPoints.end();
    1183             :     }
    1184             : };
    1185             : 
    1186             : //////////////////////////////////////////////////////////////////////////////
    1187             : 
    1188             : namespace basegfx
    1189             : {
    1190             :     namespace
    1191             :     {
    1192             :         struct DefaultPolygon: public rtl::Static<B2DPolygon::ImplType, DefaultPolygon> {};
    1193             :     }
    1194             : 
    1195       89451 :     B2DPolygon::B2DPolygon()
    1196       89451 :     :   mpPolygon(DefaultPolygon::get())
    1197       89451 :     {}
    1198             : 
    1199      366949 :     B2DPolygon::B2DPolygon(const B2DPolygon& rPolygon)
    1200      366949 :     :   mpPolygon(rPolygon.mpPolygon)
    1201      366949 :     {}
    1202             : 
    1203           0 :     B2DPolygon::B2DPolygon(const B2DPolygon& rPolygon, sal_uInt32 nIndex, sal_uInt32 nCount)
    1204           0 :     :   mpPolygon(ImplB2DPolygon(*rPolygon.mpPolygon, nIndex, nCount))
    1205             :     {
    1206             :         // TODO(P2): one extra temporary here (cow_wrapper copies
    1207             :         // given ImplB2DPolygon into its internal impl_t wrapper type)
    1208             :         OSL_ENSURE(nIndex + nCount <= rPolygon.mpPolygon->count(), "B2DPolygon constructor outside range (!)");
    1209           0 :     }
    1210             : 
    1211      456200 :     B2DPolygon::~B2DPolygon()
    1212             :     {
    1213      456200 :     }
    1214             : 
    1215        1916 :     B2DPolygon& B2DPolygon::operator=(const B2DPolygon& rPolygon)
    1216             :     {
    1217        1916 :         mpPolygon = rPolygon.mpPolygon;
    1218        1916 :         return *this;
    1219             :     }
    1220             : 
    1221          30 :     void B2DPolygon::makeUnique()
    1222             :     {
    1223          30 :         mpPolygon.make_unique();
    1224          30 :     }
    1225             : 
    1226         835 :     bool B2DPolygon::operator==(const B2DPolygon& rPolygon) const
    1227             :     {
    1228         835 :         if(mpPolygon.same_object(rPolygon.mpPolygon))
    1229          21 :             return true;
    1230             : 
    1231         814 :         return ((*mpPolygon) == (*rPolygon.mpPolygon));
    1232             :     }
    1233             : 
    1234         555 :     bool B2DPolygon::operator!=(const B2DPolygon& rPolygon) const
    1235             :     {
    1236         555 :         return !(*this == rPolygon);
    1237             :     }
    1238             : 
    1239      214282 :     sal_uInt32 B2DPolygon::count() const
    1240             :     {
    1241      214282 :         return mpPolygon->count();
    1242             :     }
    1243             : 
    1244     1269919 :     B2DPoint B2DPolygon::getB2DPoint(sal_uInt32 nIndex) const
    1245             :     {
    1246             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1247             : 
    1248     1269919 :         return mpPolygon->getPoint(nIndex);
    1249             :     }
    1250             : 
    1251      158676 :     void B2DPolygon::setB2DPoint(sal_uInt32 nIndex, const B2DPoint& rValue)
    1252             :     {
    1253             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1254             : 
    1255      158676 :         if(getB2DPoint(nIndex) != rValue)
    1256             :         {
    1257      157132 :             mpPolygon->setPoint(nIndex, rValue);
    1258             :         }
    1259      158676 :     }
    1260             : 
    1261          15 :     void B2DPolygon::reserve(sal_uInt32 nCount)
    1262             :     {
    1263          15 :         mpPolygon->reserve(nCount);
    1264          15 :     }
    1265             : 
    1266           0 :     void B2DPolygon::insert(sal_uInt32 nIndex, const B2DPoint& rPoint, sal_uInt32 nCount)
    1267             :     {
    1268             :         OSL_ENSURE(nIndex <= mpPolygon->count(), "B2DPolygon Insert outside range (!)");
    1269             : 
    1270           0 :         if(nCount)
    1271             :         {
    1272           0 :             mpPolygon->insert(nIndex, rPoint, nCount);
    1273             :         }
    1274           0 :     }
    1275             : 
    1276       51625 :     void B2DPolygon::append(const B2DPoint& rPoint, sal_uInt32 nCount)
    1277             :     {
    1278       51625 :         if(nCount)
    1279             :         {
    1280       51625 :             mpPolygon->insert(mpPolygon->count(), rPoint, nCount);
    1281             :         }
    1282       51625 :     }
    1283             : 
    1284      162568 :     void B2DPolygon::append(const B2DPoint& rPoint)
    1285             :     {
    1286      162568 :         mpPolygon->append(rPoint);
    1287      162568 :     }
    1288             : 
    1289        4373 :     B2DPoint B2DPolygon::getPrevControlPoint(sal_uInt32 nIndex) const
    1290             :     {
    1291             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1292             : 
    1293        4373 :         if(mpPolygon->areControlPointsUsed())
    1294             :         {
    1295        4202 :             return mpPolygon->getPoint(nIndex) + mpPolygon->getPrevControlVector(nIndex);
    1296             :         }
    1297             :         else
    1298             :         {
    1299         171 :             return mpPolygon->getPoint(nIndex);
    1300             :         }
    1301             :     }
    1302             : 
    1303        4247 :     B2DPoint B2DPolygon::getNextControlPoint(sal_uInt32 nIndex) const
    1304             :     {
    1305             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1306             : 
    1307        4247 :         if(mpPolygon->areControlPointsUsed())
    1308             :         {
    1309        4088 :             return mpPolygon->getPoint(nIndex) + mpPolygon->getNextControlVector(nIndex);
    1310             :         }
    1311             :         else
    1312             :         {
    1313         159 :             return mpPolygon->getPoint(nIndex);
    1314             :         }
    1315             :     }
    1316             : 
    1317          99 :     void B2DPolygon::setPrevControlPoint(sal_uInt32 nIndex, const B2DPoint& rValue)
    1318             :     {
    1319             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1320          99 :         const basegfx::B2DVector aNewVector(rValue - mpPolygon->getPoint(nIndex));
    1321             : 
    1322          99 :         if(mpPolygon->getPrevControlVector(nIndex) != aNewVector)
    1323             :         {
    1324          99 :             mpPolygon->setPrevControlVector(nIndex, aNewVector);
    1325          99 :         }
    1326          99 :     }
    1327             : 
    1328          15 :     void B2DPolygon::setNextControlPoint(sal_uInt32 nIndex, const B2DPoint& rValue)
    1329             :     {
    1330             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1331          15 :         const basegfx::B2DVector aNewVector(rValue - mpPolygon->getPoint(nIndex));
    1332             : 
    1333          15 :         if(mpPolygon->getNextControlVector(nIndex) != aNewVector)
    1334             :         {
    1335          15 :             mpPolygon->setNextControlVector(nIndex, aNewVector);
    1336          15 :         }
    1337          15 :     }
    1338             : 
    1339           1 :     void B2DPolygon::setControlPoints(sal_uInt32 nIndex, const basegfx::B2DPoint& rPrev, const basegfx::B2DPoint& rNext)
    1340             :     {
    1341             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1342           1 :         const B2DPoint aPoint(mpPolygon->getPoint(nIndex));
    1343           1 :         const basegfx::B2DVector aNewPrev(rPrev - aPoint);
    1344           1 :         const basegfx::B2DVector aNewNext(rNext - aPoint);
    1345             : 
    1346           1 :         if(mpPolygon->getPrevControlVector(nIndex) != aNewPrev || mpPolygon->getNextControlVector(nIndex) != aNewNext)
    1347             :         {
    1348           1 :             mpPolygon->setControlVectors(nIndex, aNewPrev, aNewNext);
    1349           1 :         }
    1350           1 :     }
    1351             : 
    1352           0 :     void B2DPolygon::resetPrevControlPoint(sal_uInt32 nIndex)
    1353             :     {
    1354             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1355             : 
    1356           0 :         if(mpPolygon->areControlPointsUsed() && !mpPolygon->getPrevControlVector(nIndex).equalZero())
    1357             :         {
    1358           0 :             mpPolygon->setPrevControlVector(nIndex, B2DVector::getEmptyVector());
    1359             :         }
    1360           0 :     }
    1361             : 
    1362           0 :     void B2DPolygon::resetNextControlPoint(sal_uInt32 nIndex)
    1363             :     {
    1364             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1365             : 
    1366           0 :         if(mpPolygon->areControlPointsUsed() && !mpPolygon->getNextControlVector(nIndex).equalZero())
    1367             :         {
    1368           0 :             mpPolygon->setNextControlVector(nIndex, B2DVector::getEmptyVector());
    1369             :         }
    1370           0 :     }
    1371             : 
    1372           1 :     void B2DPolygon::resetControlPoints()
    1373             :     {
    1374           1 :         if(mpPolygon->areControlPointsUsed())
    1375             :         {
    1376           1 :             mpPolygon->resetControlVectors();
    1377             :         }
    1378           1 :     }
    1379             : 
    1380        2217 :     void B2DPolygon::appendBezierSegment(
    1381             :         const B2DPoint& rNextControlPoint,
    1382             :         const B2DPoint& rPrevControlPoint,
    1383             :         const B2DPoint& rPoint)
    1384             :     {
    1385        2217 :         const B2DVector aNewNextVector(mpPolygon->count() ? B2DVector(rNextControlPoint - mpPolygon->getPoint(mpPolygon->count() - 1)) : B2DVector::getEmptyVector());
    1386        2217 :         const B2DVector aNewPrevVector(rPrevControlPoint - rPoint);
    1387             : 
    1388        2217 :         if(aNewNextVector.equalZero() && aNewPrevVector.equalZero())
    1389             :         {
    1390           7 :             mpPolygon->insert(mpPolygon->count(), rPoint, 1);
    1391             :         }
    1392             :         else
    1393             :         {
    1394        2210 :             mpPolygon->appendBezierSegment(aNewNextVector, aNewPrevVector, rPoint);
    1395        2217 :         }
    1396        2217 :     }
    1397             : 
    1398      183525 :     bool B2DPolygon::areControlPointsUsed() const
    1399             :     {
    1400      183525 :         return mpPolygon->areControlPointsUsed();
    1401             :     }
    1402             : 
    1403         302 :     bool B2DPolygon::isPrevControlPointUsed(sal_uInt32 nIndex) const
    1404             :     {
    1405             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1406             : 
    1407         302 :         return (mpPolygon->areControlPointsUsed() && !mpPolygon->getPrevControlVector(nIndex).equalZero());
    1408             :     }
    1409             : 
    1410         181 :     bool B2DPolygon::isNextControlPointUsed(sal_uInt32 nIndex) const
    1411             :     {
    1412             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1413             : 
    1414         181 :         return (mpPolygon->areControlPointsUsed() && !mpPolygon->getNextControlVector(nIndex).equalZero());
    1415             :     }
    1416             : 
    1417        2523 :     B2VectorContinuity B2DPolygon::getContinuityInPoint(sal_uInt32 nIndex) const
    1418             :     {
    1419             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1420             : 
    1421        2523 :         if(mpPolygon->areControlPointsUsed())
    1422             :         {
    1423        2523 :             const B2DVector& rPrev(mpPolygon->getPrevControlVector(nIndex));
    1424        2523 :             const B2DVector& rNext(mpPolygon->getNextControlVector(nIndex));
    1425             : 
    1426        2523 :             return getContinuity(rPrev, rNext);
    1427             :         }
    1428             :         else
    1429             :         {
    1430           0 :             return CONTINUITY_NONE;
    1431             :         }
    1432             :     }
    1433             : 
    1434        2819 :     void B2DPolygon::getBezierSegment(sal_uInt32 nIndex, B2DCubicBezier& rTarget) const
    1435             :     {
    1436             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1437        2819 :         const bool bNextIndexValidWithoutClose(nIndex + 1 < mpPolygon->count());
    1438             : 
    1439        2819 :         if(bNextIndexValidWithoutClose || mpPolygon->isClosed())
    1440             :         {
    1441        2757 :             const sal_uInt32 nNextIndex(bNextIndexValidWithoutClose ? nIndex + 1 : 0);
    1442        2757 :             rTarget.setStartPoint(mpPolygon->getPoint(nIndex));
    1443        2757 :             rTarget.setEndPoint(mpPolygon->getPoint(nNextIndex));
    1444             : 
    1445        2757 :             if(mpPolygon->areControlPointsUsed())
    1446             :             {
    1447         109 :                 rTarget.setControlPointA(rTarget.getStartPoint() + mpPolygon->getNextControlVector(nIndex));
    1448         109 :                 rTarget.setControlPointB(rTarget.getEndPoint() + mpPolygon->getPrevControlVector(nNextIndex));
    1449             :             }
    1450             :             else
    1451             :             {
    1452             :                 // no bezier, reset control poins at rTarget
    1453        2648 :                 rTarget.setControlPointA(rTarget.getStartPoint());
    1454        2648 :                 rTarget.setControlPointB(rTarget.getEndPoint());
    1455             :             }
    1456             :         }
    1457             :         else
    1458             :         {
    1459             :             // no valid edge at all, reset rTarget to current point
    1460          62 :             const B2DPoint aPoint(mpPolygon->getPoint(nIndex));
    1461          62 :             rTarget.setStartPoint(aPoint);
    1462          62 :             rTarget.setEndPoint(aPoint);
    1463          62 :             rTarget.setControlPointA(aPoint);
    1464          62 :             rTarget.setControlPointB(aPoint);
    1465             :         }
    1466        2819 :     }
    1467             : 
    1468           0 :     B2DPolygon B2DPolygon::getDefaultAdaptiveSubdivision() const
    1469             :     {
    1470           0 :         return mpPolygon->getDefaultAdaptiveSubdivision(*this);
    1471             :     }
    1472             : 
    1473       83226 :     B2DRange B2DPolygon::getB2DRange() const
    1474             :     {
    1475       83226 :         return mpPolygon->getB2DRange(*this);
    1476             :     }
    1477             : 
    1478           0 :     void B2DPolygon::append(const B2DPolygon& rPoly, sal_uInt32 nIndex, sal_uInt32 nCount)
    1479             :     {
    1480           0 :         if(rPoly.count())
    1481             :         {
    1482           0 :             if(!nCount)
    1483             :             {
    1484           0 :                 nCount = rPoly.count();
    1485             :             }
    1486             : 
    1487           0 :             if(0 == nIndex && nCount == rPoly.count())
    1488             :             {
    1489           0 :                 mpPolygon->insert(mpPolygon->count(), *rPoly.mpPolygon);
    1490             :             }
    1491             :             else
    1492             :             {
    1493             :                 OSL_ENSURE(nIndex + nCount <= rPoly.mpPolygon->count(), "B2DPolygon Append outside range (!)");
    1494           0 :                 ImplB2DPolygon aTempPoly(*rPoly.mpPolygon, nIndex, nCount);
    1495           0 :                 mpPolygon->insert(mpPolygon->count(), aTempPoly);
    1496             :             }
    1497             :         }
    1498           0 :     }
    1499             : 
    1500        1222 :     void B2DPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount)
    1501             :     {
    1502             :         OSL_ENSURE(nIndex + nCount <= mpPolygon->count(), "B2DPolygon Remove outside range (!)");
    1503             : 
    1504        1222 :         if(nCount)
    1505             :         {
    1506        1222 :             mpPolygon->remove(nIndex, nCount);
    1507             :         }
    1508        1222 :     }
    1509             : 
    1510        1977 :     void B2DPolygon::clear()
    1511             :     {
    1512        1977 :         mpPolygon = DefaultPolygon::get();
    1513        1977 :     }
    1514             : 
    1515      100359 :     bool B2DPolygon::isClosed() const
    1516             :     {
    1517      100359 :         return mpPolygon->isClosed();
    1518             :     }
    1519             : 
    1520       85342 :     void B2DPolygon::setClosed(bool bNew)
    1521             :     {
    1522       85342 :         if(isClosed() != bNew)
    1523             :         {
    1524       82450 :             mpPolygon->setClosed(bNew);
    1525             :         }
    1526       85342 :     }
    1527             : 
    1528         587 :     void B2DPolygon::flip()
    1529             :     {
    1530         587 :         if(count() > 1)
    1531             :         {
    1532         587 :             mpPolygon->flip();
    1533             :         }
    1534         587 :     }
    1535             : 
    1536         517 :     bool B2DPolygon::hasDoublePoints() const
    1537             :     {
    1538         517 :         return (mpPolygon->count() > 1 && mpPolygon->hasDoublePoints());
    1539             :     }
    1540             : 
    1541         128 :     void B2DPolygon::removeDoublePoints()
    1542             :     {
    1543         128 :         if(hasDoublePoints())
    1544             :         {
    1545          17 :             mpPolygon->removeDoublePointsAtBeginEnd();
    1546          17 :             mpPolygon->removeDoublePointsWholeTrack();
    1547             :         }
    1548         128 :     }
    1549             : 
    1550        3972 :     void B2DPolygon::transform(const B2DHomMatrix& rMatrix)
    1551             :     {
    1552        3972 :         if(mpPolygon->count() && !rMatrix.isIdentity())
    1553             :         {
    1554        3212 :             mpPolygon->transform(rMatrix);
    1555             :         }
    1556        3972 :     }
    1557             : 
    1558             : } // end of namespace basegfx
    1559             : 
    1560             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10