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-17 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     2903093 : struct CoordinateData2D : public basegfx::B2DPoint
      35             : {
      36             : public:
      37           0 :     CoordinateData2D() {}
      38             : 
      39      499353 :     explicit CoordinateData2D(const basegfx::B2DPoint& rData)
      40      499353 :     :   B2DPoint(rData)
      41      499353 :     {}
      42             : 
      43      371565 :     CoordinateData2D& operator=(const basegfx::B2DPoint& rData)
      44             :     {
      45      371565 :         B2DPoint::operator=(rData);
      46      371565 :         return *this;
      47             :     }
      48             : 
      49       19040 :     void transform(const basegfx::B2DHomMatrix& rMatrix)
      50             :     {
      51       19040 :         *this *= rMatrix;
      52       19040 :     }
      53             : };
      54             : 
      55             : //////////////////////////////////////////////////////////////////////////////
      56             : 
      57      220420 : class CoordinateDataArray2D
      58             : {
      59             :     typedef ::std::vector< CoordinateData2D > CoordinateData2DVector;
      60             : 
      61             :     CoordinateData2DVector                          maVector;
      62             : 
      63             : public:
      64          80 :     explicit CoordinateDataArray2D(sal_uInt32 nCount)
      65          80 :     :   maVector(nCount)
      66             :     {
      67          80 :     }
      68             : 
      69      220754 :     explicit CoordinateDataArray2D(const CoordinateDataArray2D& rOriginal)
      70      220754 :     :   maVector(rOriginal.maVector)
      71             :     {
      72      220754 :     }
      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      635065 :     sal_uInt32 count() const
      80             :     {
      81      635065 :         return maVector.size();
      82             :     }
      83             : 
      84        1090 :     bool operator==(const CoordinateDataArray2D& rCandidate) const
      85             :     {
      86        1090 :         return (maVector == rCandidate.maVector);
      87             :     }
      88             : 
      89     2913860 :     const basegfx::B2DPoint& getCoordinate(sal_uInt32 nIndex) const
      90             :     {
      91     2913860 :         return maVector[nIndex];
      92             :     }
      93             : 
      94      371565 :     void setCoordinate(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue)
      95             :     {
      96      371565 :         maVector[nIndex] = rValue;
      97      371565 :     }
      98             : 
      99          30 :     void reserve(sal_uInt32 nCount)
     100             :     {
     101          30 :         maVector.reserve(nCount);
     102          30 :     }
     103             : 
     104      374338 :     void append(const CoordinateData2D& rValue)
     105             :     {
     106      374338 :         maVector.push_back(rValue);
     107      374338 :     }
     108             : 
     109      125015 :     void insert(sal_uInt32 nIndex, const CoordinateData2D& rValue, sal_uInt32 nCount)
     110             :     {
     111      125015 :         if(nCount)
     112             :         {
     113             :             // add nCount copies of rValue
     114      125015 :             CoordinateData2DVector::iterator aIndex(maVector.begin());
     115      125015 :             aIndex += nIndex;
     116      125015 :             maVector.insert(aIndex, nCount, rValue);
     117             :         }
     118      125015 :     }
     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        2116 :     void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
     136             :     {
     137        2116 :         if(nCount)
     138             :         {
     139             :             // remove point data
     140        2116 :             CoordinateData2DVector::iterator aStart(maVector.begin());
     141        2116 :             aStart += nIndex;
     142        2116 :             const CoordinateData2DVector::iterator aEnd(aStart + nCount);
     143        2116 :             maVector.erase(aStart, aEnd);
     144             :         }
     145        2116 :     }
     146             : 
     147         842 :     void flip(bool bIsClosed)
     148             :     {
     149         842 :         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         842 :             const sal_uInt32 nHalfSize(bIsClosed ? (maVector.size() - 1) >> 1 : maVector.size() >> 1);
     154         842 :             CoordinateData2DVector::iterator aStart(bIsClosed ? maVector.begin() + 1 : maVector.begin());
     155         842 :             CoordinateData2DVector::iterator aEnd(maVector.end() - 1);
     156             : 
     157        2286 :             for(sal_uInt32 a(0); a < nHalfSize; a++)
     158             :             {
     159        1444 :                 ::std::swap(*aStart, *aEnd);
     160        1444 :                 ++aStart;
     161        1444 :                 --aEnd;
     162             :             }
     163             :         }
     164         842 :     }
     165             : 
     166          34 :     void removeDoublePointsAtBeginEnd()
     167             :     {
     168             :         // remove from end as long as there are at least two points
     169             :         // and begin/end are equal
     170          74 :         while((maVector.size() > 1) && (maVector[0] == maVector[maVector.size() - 1]))
     171             :         {
     172           6 :             maVector.pop_back();
     173             :         }
     174          34 :     }
     175             : 
     176          34 :     void removeDoublePointsWholeTrack()
     177             :     {
     178          34 :         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         214 :         while((maVector.size() > 1) && (nIndex <= maVector.size() - 2))
     183             :         {
     184         146 :             if(maVector[nIndex] == maVector[nIndex + 1])
     185             :             {
     186             :                 // if next is same as index, delete next
     187          28 :                 maVector.erase(maVector.begin() + (nIndex + 1));
     188             :             }
     189             :             else
     190             :             {
     191             :                 // if different, step forward
     192         118 :                 nIndex++;
     193             :             }
     194             :         }
     195          34 :     }
     196             : 
     197        6254 :     void transform(const basegfx::B2DHomMatrix& rMatrix)
     198             :     {
     199        6254 :         CoordinateData2DVector::iterator aStart(maVector.begin());
     200        6254 :         CoordinateData2DVector::iterator aEnd(maVector.end());
     201             : 
     202       25294 :         for(; aStart != aEnd; ++aStart)
     203             :         {
     204       19040 :             aStart->transform(rMatrix);
     205             :         }
     206        6254 :     }
     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       45218 : class ControlVectorPair2D
     244             : {
     245             :     basegfx::B2DVector                          maPrevVector;
     246             :     basegfx::B2DVector                          maNextVector;
     247             : 
     248             : public:
     249        6864 :     explicit ControlVectorPair2D() {}
     250             : 
     251       37080 :     const basegfx::B2DVector& getPrevVector() const
     252             :     {
     253       37080 :         return maPrevVector;
     254             :     }
     255             : 
     256        9164 :     void setPrevVector(const basegfx::B2DVector& rValue)
     257             :     {
     258        9164 :         if(rValue != maPrevVector)
     259        8682 :             maPrevVector = rValue;
     260        9164 :     }
     261             : 
     262       35928 :     const basegfx::B2DVector& getNextVector() const
     263             :     {
     264       35928 :         return maNextVector;
     265             :     }
     266             : 
     267        9212 :     void setNextVector(const basegfx::B2DVector& rValue)
     268             :     {
     269        9212 :         if(rValue != maNextVector)
     270        8716 :             maNextVector = rValue;
     271        9212 :     }
     272             : 
     273         234 :     bool operator==(const ControlVectorPair2D& rData) const
     274             :     {
     275         234 :         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         674 : class ControlVectorArray2D
     287             : {
     288             :     typedef ::std::vector< ControlVectorPair2D > ControlVectorPair2DVector;
     289             : 
     290             :     ControlVectorPair2DVector                           maVector;
     291             :     sal_uInt32                                          mnUsedVectors;
     292             : 
     293             : public:
     294         458 :     explicit ControlVectorArray2D(sal_uInt32 nCount)
     295             :     :   maVector(nCount),
     296         458 :         mnUsedVectors(0)
     297         458 :     {}
     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          18 :     bool operator==(const ControlVectorArray2D& rCandidate) const
     327             :     {
     328          18 :         return (maVector == rCandidate.maVector);
     329             :     }
     330             : 
     331       40292 :     bool isUsed() const
     332             :     {
     333       40292 :         return (0 != mnUsedVectors);
     334             :     }
     335             : 
     336       21170 :     const basegfx::B2DVector& getPrevVector(sal_uInt32 nIndex) const
     337             :     {
     338       21170 :         return maVector[nIndex].getPrevVector();
     339             :     }
     340             : 
     341        9284 :     void setPrevVector(sal_uInt32 nIndex, const basegfx::B2DVector& rValue)
     342             :     {
     343        9284 :         bool bWasUsed(mnUsedVectors && !maVector[nIndex].getPrevVector().equalZero());
     344        9284 :         bool bIsUsed(!rValue.equalZero());
     345             : 
     346        9284 :         if(bWasUsed)
     347             :         {
     348        4690 :             if(bIsUsed)
     349             :             {
     350        4690 :                 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        4594 :             if(bIsUsed)
     361             :             {
     362        4474 :                 maVector[nIndex].setPrevVector(rValue);
     363        4474 :                 mnUsedVectors++;
     364             :             }
     365             :         }
     366        9284 :     }
     367             : 
     368       20528 :     const basegfx::B2DVector& getNextVector(sal_uInt32 nIndex) const
     369             :     {
     370       20528 :         return maVector[nIndex].getNextVector();
     371             :     }
     372             : 
     373        9228 :     void setNextVector(sal_uInt32 nIndex, const basegfx::B2DVector& rValue)
     374             :     {
     375        9228 :         bool bWasUsed(mnUsedVectors && !maVector[nIndex].getNextVector().equalZero());
     376        9228 :         bool bIsUsed(!rValue.equalZero());
     377             : 
     378        9228 :         if(bWasUsed)
     379             :         {
     380        4802 :             if(bIsUsed)
     381             :             {
     382        4802 :                 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        4426 :             if(bIsUsed)
     393             :             {
     394        4410 :                 maVector[nIndex].setNextVector(rValue);
     395        4410 :                 mnUsedVectors++;
     396             :             }
     397             :         }
     398        9228 :     }
     399             : 
     400        1506 :     void append(const ControlVectorPair2D& rValue)
     401             :     {
     402        1506 :         maVector.push_back(rValue);
     403             : 
     404        1506 :         if(!rValue.getPrevVector().equalZero())
     405           0 :             mnUsedVectors += 1;
     406             : 
     407        1506 :         if(!rValue.getNextVector().equalZero())
     408           0 :             mnUsedVectors += 1;
     409        1506 :     }
     410             : 
     411        4426 :     void insert(sal_uInt32 nIndex, const ControlVectorPair2D& rValue, sal_uInt32 nCount)
     412             :     {
     413        4426 :         if(nCount)
     414             :         {
     415             :             // add nCount copies of rValue
     416        4426 :             ControlVectorPair2DVector::iterator aIndex(maVector.begin());
     417        4426 :             aIndex += nIndex;
     418        4426 :             maVector.insert(aIndex, nCount, rValue);
     419             : 
     420        4426 :             if(!rValue.getPrevVector().equalZero())
     421           0 :                 mnUsedVectors += nCount;
     422             : 
     423        4426 :             if(!rValue.getNextVector().equalZero())
     424           0 :                 mnUsedVectors += nCount;
     425             :         }
     426        4426 :     }
     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         426 :     void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
     453             :     {
     454         426 :         if(nCount)
     455             :         {
     456         426 :             const ControlVectorPair2DVector::iterator aDeleteStart(maVector.begin() + nIndex);
     457         426 :             const ControlVectorPair2DVector::iterator aDeleteEnd(aDeleteStart + nCount);
     458         426 :             ControlVectorPair2DVector::const_iterator aStart(aDeleteStart);
     459             : 
     460         888 :             for(; mnUsedVectors && aStart != aDeleteEnd; ++aStart)
     461             :             {
     462         462 :                 if(!aStart->getPrevVector().equalZero())
     463         170 :                     mnUsedVectors--;
     464             : 
     465         462 :                 if(mnUsedVectors && !aStart->getNextVector().equalZero())
     466           0 :                     mnUsedVectors--;
     467             :             }
     468             : 
     469             :             // remove point data
     470         426 :             maVector.erase(aDeleteStart, aDeleteEnd);
     471             :         }
     472         426 :     }
     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      195777 : 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      195885 :     ImplBufferedData()
     525             :     :   mpDefaultSubdivision(),
     526      195885 :         mpB2DRange()
     527      195885 :     {}
     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      196341 :     const basegfx::B2DRange& getB2DRange(const basegfx::B2DPolygon& rSource) const
     540             :     {
     541      196341 :         if(!mpB2DRange)
     542             :         {
     543      195885 :             basegfx::B2DRange aNewRange;
     544      195885 :             const sal_uInt32 nPointCount(rSource.count());
     545             : 
     546      195885 :             if(nPointCount)
     547             :             {
     548      986877 :                 for(sal_uInt32 a(0); a < nPointCount; a++)
     549             :                 {
     550      790992 :                     aNewRange.expand(rSource.getB2DPoint(a));
     551             :                 }
     552             : 
     553      195885 :                 if(rSource.areControlPointsUsed())
     554             :                 {
     555          70 :                     const sal_uInt32 nEdgeCount(rSource.isClosed() ? nPointCount : nPointCount - 1);
     556             : 
     557          70 :                     if(nEdgeCount)
     558             :                     {
     559          70 :                         basegfx::B2DCubicBezier aEdge;
     560          70 :                         aEdge.setStartPoint(rSource.getB2DPoint(0));
     561             : 
     562         940 :                         for(sal_uInt32 b(0); b < nEdgeCount; b++)
     563             :                         {
     564         870 :                             const sal_uInt32 nNextIndex((b + 1) % nPointCount);
     565         870 :                             aEdge.setControlPointA(rSource.getNextControlPoint(b));
     566         870 :                             aEdge.setControlPointB(rSource.getPrevControlPoint(nNextIndex));
     567         870 :                             aEdge.setEndPoint(rSource.getB2DPoint(nNextIndex));
     568             : 
     569         870 :                             if(aEdge.isBezier())
     570             :                             {
     571         782 :                                 const basegfx::B2DRange aBezierRangeWithControlPoints(aEdge.getRange());
     572             : 
     573         782 :                                 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         204 :                                     ::std::vector< double > aExtremas;
     581             : 
     582         204 :                                     aExtremas.reserve(4);
     583         204 :                                     aEdge.getAllExtremumPositions(aExtremas);
     584             : 
     585         204 :                                     const sal_uInt32 nExtremaCount(aExtremas.size());
     586             : 
     587         474 :                                     for(sal_uInt32 c(0); c < nExtremaCount; c++)
     588             :                                     {
     589         270 :                                         aNewRange.expand(aEdge.interpolatePoint(aExtremas[c]));
     590         204 :                                     }
     591             :                                 }
     592             :                             }
     593             : 
     594             :                             // prepare next edge
     595         870 :                             aEdge.setStartPoint(aEdge.getEndPoint());
     596          70 :                         }
     597             :                     }
     598             :                 }
     599             :             }
     600             : 
     601      195885 :             const_cast< ImplBufferedData* >(this)->mpB2DRange.reset(new basegfx::B2DRange(aNewRange));
     602             :         }
     603             : 
     604      196341 :         return *mpB2DRange;
     605             :     }
     606             : };
     607             : 
     608             : //////////////////////////////////////////////////////////////////////////////
     609             : 
     610      220420 : 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      196341 :     const basegfx::B2DRange& getB2DRange(const basegfx::B2DPolygon& rSource) const
     644             :     {
     645      196341 :         if(!mpBufferedData)
     646             :         {
     647      195885 :             const_cast< ImplB2DPolygon* >(this)->mpBufferedData.reset(new ImplBufferedData);
     648             :         }
     649             : 
     650      196341 :         return mpBufferedData->getB2DRange(rSource);
     651             :     }
     652             : 
     653          80 :     ImplB2DPolygon()
     654             :     :   maPoints(0),
     655             :         mpControlVector(),
     656             :         mpBufferedData(),
     657          80 :         mbIsClosed(false)
     658          80 :     {}
     659             : 
     660      220754 :     ImplB2DPolygon(const ImplB2DPolygon& rToBeCopied)
     661             :     :   maPoints(rToBeCopied.maPoints),
     662             :         mpControlVector(),
     663             :         mpBufferedData(),
     664      220754 :         mbIsClosed(rToBeCopied.mbIsClosed)
     665             :     {
     666             :         // complete initialization using copy
     667      220754 :         if(rToBeCopied.mpControlVector && rToBeCopied.mpControlVector->isUsed())
     668             :         {
     669         118 :             mpControlVector.reset( new ControlVectorArray2D(*rToBeCopied.mpControlVector) );
     670             :         }
     671      220754 :     }
     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      617461 :     sal_uInt32 count() const
     704             :     {
     705      617461 :         return maPoints.count();
     706             :     }
     707             : 
     708      230742 :     bool isClosed() const
     709             :     {
     710      230742 :         return mbIsClosed;
     711             :     }
     712             : 
     713      194495 :     void setClosed(bool bNew)
     714             :     {
     715      194495 :         if(bNew != mbIsClosed)
     716             :         {
     717      194495 :             mpBufferedData.reset();
     718      194495 :             mbIsClosed = bNew;
     719             :         }
     720      194495 :     }
     721             : 
     722        1236 :     bool operator==(const ImplB2DPolygon& rCandidate) const
     723             :     {
     724        1236 :         if(mbIsClosed == rCandidate.mbIsClosed)
     725             :         {
     726        1090 :             if(maPoints == rCandidate.maPoints)
     727             :             {
     728         454 :                 bool bControlVectorsAreEqual(true);
     729             : 
     730         454 :                 if(mpControlVector)
     731             :                 {
     732          18 :                     if(rCandidate.mpControlVector)
     733             :                     {
     734          18 :                         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         436 :                     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         454 :                 if(bControlVectorsAreEqual)
     752             :                 {
     753         454 :                     return true;
     754             :                 }
     755             :             }
     756             :         }
     757             : 
     758         782 :         return false;
     759             :     }
     760             : 
     761     2899064 :     const basegfx::B2DPoint& getPoint(sal_uInt32 nIndex) const
     762             :     {
     763     2899064 :         return maPoints.getCoordinate(nIndex);
     764             :     }
     765             : 
     766      364817 :     void setPoint(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue)
     767             :     {
     768      364817 :         mpBufferedData.reset();
     769      364817 :         maPoints.setCoordinate(nIndex, rValue);
     770      364817 :     }
     771             : 
     772          30 :     void reserve(sal_uInt32 nCount)
     773             :     {
     774          30 :         maPoints.reserve(nCount);
     775          30 :     }
     776             : 
     777      374338 :     void append(const basegfx::B2DPoint& rPoint)
     778             :     {
     779      374338 :         mpBufferedData.reset(); // TODO: is this needed?
     780      374338 :         const CoordinateData2D aCoordinate(rPoint);
     781      374338 :         maPoints.append(aCoordinate);
     782             : 
     783      374338 :         if(mpControlVector)
     784             :         {
     785        1506 :             const ControlVectorPair2D aVectorPair;
     786        1506 :             mpControlVector->append(aVectorPair);
     787      374338 :         }
     788      374338 :     }
     789             : 
     790      125015 :     void insert(sal_uInt32 nIndex, const basegfx::B2DPoint& rPoint, sal_uInt32 nCount)
     791             :     {
     792      125015 :         if(nCount)
     793             :         {
     794      125015 :             mpBufferedData.reset();
     795      125015 :             CoordinateData2D aCoordinate(rPoint);
     796      125015 :             maPoints.insert(nIndex, aCoordinate, nCount);
     797             : 
     798      125015 :             if(mpControlVector)
     799             :             {
     800        4426 :                 ControlVectorPair2D aVectorPair;
     801        4426 :                 mpControlVector->insert(nIndex, aVectorPair, nCount);
     802      125015 :             }
     803             :         }
     804      125015 :     }
     805             : 
     806       14424 :     const basegfx::B2DVector& getPrevControlVector(sal_uInt32 nIndex) const
     807             :     {
     808       14424 :         if(mpControlVector)
     809             :         {
     810       14422 :             return mpControlVector->getPrevVector(nIndex);
     811             :         }
     812             :         else
     813             :         {
     814           2 :             return basegfx::B2DVector::getEmptyVector();
     815             :         }
     816             :     }
     817             : 
     818        4620 :     void setPrevControlVector(sal_uInt32 nIndex, const basegfx::B2DVector& rValue)
     819             :     {
     820        4620 :         if(!mpControlVector)
     821             :         {
     822           4 :             if(!rValue.equalZero())
     823             :             {
     824           2 :                 mpBufferedData.reset();
     825           2 :                 mpControlVector.reset( new ControlVectorArray2D(maPoints.count()) );
     826           2 :                 mpControlVector->setPrevVector(nIndex, rValue);
     827             :             }
     828             :         }
     829             :         else
     830             :         {
     831        4616 :             mpBufferedData.reset();
     832        4616 :             mpControlVector->setPrevVector(nIndex, rValue);
     833             : 
     834        4616 :             if(!mpControlVector->isUsed())
     835           0 :                 mpControlVector.reset();
     836             :         }
     837        4620 :     }
     838             : 
     839       13786 :     const basegfx::B2DVector& getNextControlVector(sal_uInt32 nIndex) const
     840             :     {
     841       13786 :         if(mpControlVector)
     842             :         {
     843       13780 :             return mpControlVector->getNextVector(nIndex);
     844             :         }
     845             :         else
     846             :         {
     847           6 :             return basegfx::B2DVector::getEmptyVector();
     848             :         }
     849             :     }
     850             : 
     851        4450 :     void setNextControlVector(sal_uInt32 nIndex, const basegfx::B2DVector& rValue)
     852             :     {
     853        4450 :         if(!mpControlVector)
     854             :         {
     855         456 :             if(!rValue.equalZero())
     856             :             {
     857         456 :                 mpBufferedData.reset();
     858         456 :                 mpControlVector.reset( new ControlVectorArray2D(maPoints.count()) );
     859         456 :                 mpControlVector->setNextVector(nIndex, rValue);
     860             :             }
     861             :         }
     862             :         else
     863             :         {
     864        3994 :             mpBufferedData.reset();
     865        3994 :             mpControlVector->setNextVector(nIndex, rValue);
     866             : 
     867        3994 :             if(!mpControlVector->isUsed())
     868           0 :                 mpControlVector.reset();
     869             :         }
     870        4450 :     }
     871             : 
     872      446378 :     bool areControlPointsUsed() const
     873             :     {
     874      446378 :         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           2 :     void resetControlVectors()
     884             :     {
     885           2 :         mpBufferedData.reset();
     886           2 :         mpControlVector.reset();
     887           2 :     }
     888             : 
     889           2 :     void setControlVectors(sal_uInt32 nIndex, const basegfx::B2DVector& rPrev, const basegfx::B2DVector& rNext)
     890             :     {
     891           2 :         setPrevControlVector(nIndex, rPrev);
     892           2 :         setNextControlVector(nIndex, rNext);
     893           2 :     }
     894             : 
     895        4420 :     void appendBezierSegment(const basegfx::B2DVector& rNext, const basegfx::B2DVector& rPrev, const basegfx::B2DPoint& rPoint)
     896             :     {
     897        4420 :         mpBufferedData.reset();
     898        4420 :         const sal_uInt32 nCount(maPoints.count());
     899             : 
     900        4420 :         if(nCount)
     901             :         {
     902        4418 :             setNextControlVector(nCount - 1, rNext);
     903             :         }
     904             : 
     905        4420 :         insert(nCount, rPoint, 1);
     906        4420 :         setPrevControlVector(nCount, rPrev);
     907        4420 :     }
     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        2116 :     void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
     940             :     {
     941        2116 :         if(nCount)
     942             :         {
     943        2116 :             mpBufferedData.reset();
     944        2116 :             maPoints.remove(nIndex, nCount);
     945             : 
     946        2116 :             if(mpControlVector)
     947             :             {
     948         426 :                 mpControlVector->remove(nIndex, nCount);
     949             : 
     950         426 :                 if(!mpControlVector->isUsed())
     951           0 :                     mpControlVector.reset();
     952             :             }
     953             :         }
     954        2116 :     }
     955             : 
     956         842 :     void flip()
     957             :     {
     958         842 :         if(maPoints.count() > 1)
     959             :         {
     960         842 :             mpBufferedData.reset();
     961             : 
     962             :             // flip points
     963         842 :             maPoints.flip(mbIsClosed);
     964             : 
     965         842 :             if(mpControlVector)
     966             :             {
     967             :                 // flip control vector
     968           0 :                 mpControlVector->flip(mbIsClosed);
     969             :             }
     970             :         }
     971         842 :     }
     972             : 
     973         696 :     bool hasDoublePoints() const
     974             :     {
     975         696 :         if(mbIsClosed)
     976             :         {
     977             :             // check for same start and end point
     978         500 :             const sal_uInt32 nIndex(maPoints.count() - 1);
     979             : 
     980         500 :             if(maPoints.getCoordinate(0) == maPoints.getCoordinate(nIndex))
     981             :             {
     982           6 :                 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           6 :                     return true;
     992             :                 }
     993             :             }
     994             :         }
     995             : 
     996             :         // test for range
     997        4162 :         for(sal_uInt32 a(0); a < maPoints.count() - 1; a++)
     998             :         {
     999        3524 :             if(maPoints.getCoordinate(a) == maPoints.getCoordinate(a + 1))
    1000             :             {
    1001          52 :                 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          52 :                     return true;
    1011             :                 }
    1012             :             }
    1013             :         }
    1014             : 
    1015         638 :         return false;
    1016             :     }
    1017             : 
    1018          34 :     void removeDoublePointsAtBeginEnd()
    1019             :     {
    1020             :         // Only remove DoublePoints at Begin and End when poly is closed
    1021          34 :         if(mbIsClosed)
    1022             :         {
    1023          34 :             mpBufferedData.reset();
    1024             : 
    1025          34 :             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          34 :                 maPoints.removeDoublePointsAtBeginEnd();
    1070             :             }
    1071             :         }
    1072          34 :     }
    1073             : 
    1074          34 :     void removeDoublePointsWholeTrack()
    1075             :     {
    1076          34 :         mpBufferedData.reset();
    1077             : 
    1078          34 :         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          34 :             maPoints.removeDoublePointsWholeTrack();
    1119             :         }
    1120          34 :     }
    1121             : 
    1122        6728 :     void transform(const basegfx::B2DHomMatrix& rMatrix)
    1123             :     {
    1124        6728 :         mpBufferedData.reset();
    1125             : 
    1126        6728 :         if(mpControlVector)
    1127             :         {
    1128        7222 :             for(sal_uInt32 a(0); a < maPoints.count(); a++)
    1129             :             {
    1130        6748 :                 basegfx::B2DPoint aCandidate = maPoints.getCoordinate(a);
    1131             : 
    1132        6748 :                 if(mpControlVector->isUsed())
    1133             :                 {
    1134        6748 :                     const basegfx::B2DVector& rPrevVector(mpControlVector->getPrevVector(a));
    1135        6748 :                     const basegfx::B2DVector& rNextVector(mpControlVector->getNextVector(a));
    1136             : 
    1137        6748 :                     if(!rPrevVector.equalZero())
    1138             :                     {
    1139        4666 :                         basegfx::B2DVector aPrevVector(rMatrix * rPrevVector);
    1140        4666 :                         mpControlVector->setPrevVector(a, aPrevVector);
    1141             :                     }
    1142             : 
    1143        6748 :                     if(!rNextVector.equalZero())
    1144             :                     {
    1145        4778 :                         basegfx::B2DVector aNextVector(rMatrix * rNextVector);
    1146        4778 :                         mpControlVector->setNextVector(a, aNextVector);
    1147             :                     }
    1148             :                 }
    1149             : 
    1150        6748 :                 aCandidate *= rMatrix;
    1151        6748 :                 maPoints.setCoordinate(a, aCandidate);
    1152        6748 :             }
    1153             : 
    1154         474 :             if(!mpControlVector->isUsed())
    1155           0 :                 mpControlVector.reset();
    1156             :         }
    1157             :         else
    1158             :         {
    1159        6254 :             maPoints.transform(rMatrix);
    1160             :         }
    1161        6728 :     }
    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      208794 :     B2DPolygon::B2DPolygon()
    1196      208794 :     :   mpPolygon(DefaultPolygon::get())
    1197      208794 :     {}
    1198             : 
    1199      846791 :     B2DPolygon::B2DPolygon(const B2DPolygon& rPolygon)
    1200      846791 :     :   mpPolygon(rPolygon.mpPolygon)
    1201      846791 :     {}
    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     1055095 :     B2DPolygon::~B2DPolygon()
    1212             :     {
    1213     1055095 :     }
    1214             : 
    1215        3112 :     B2DPolygon& B2DPolygon::operator=(const B2DPolygon& rPolygon)
    1216             :     {
    1217        3112 :         mpPolygon = rPolygon.mpPolygon;
    1218        3112 :         return *this;
    1219             :     }
    1220             : 
    1221          60 :     void B2DPolygon::makeUnique()
    1222             :     {
    1223          60 :         mpPolygon.make_unique();
    1224          60 :     }
    1225             : 
    1226        1278 :     bool B2DPolygon::operator==(const B2DPolygon& rPolygon) const
    1227             :     {
    1228        1278 :         if(mpPolygon.same_object(rPolygon.mpPolygon))
    1229          42 :             return true;
    1230             : 
    1231        1236 :         return ((*mpPolygon) == (*rPolygon.mpPolygon));
    1232             :     }
    1233             : 
    1234         720 :     bool B2DPolygon::operator!=(const B2DPolygon& rPolygon) const
    1235             :     {
    1236         720 :         return !(*this == rPolygon);
    1237             :     }
    1238             : 
    1239      475898 :     sal_uInt32 B2DPolygon::count() const
    1240             :     {
    1241      475898 :         return mpPolygon->count();
    1242             :     }
    1243             : 
    1244     2871958 :     B2DPoint B2DPolygon::getB2DPoint(sal_uInt32 nIndex) const
    1245             :     {
    1246             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1247             : 
    1248     2871958 :         return mpPolygon->getPoint(nIndex);
    1249             :     }
    1250             : 
    1251      368472 :     void B2DPolygon::setB2DPoint(sal_uInt32 nIndex, const B2DPoint& rValue)
    1252             :     {
    1253             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1254             : 
    1255      368472 :         if(getB2DPoint(nIndex) != rValue)
    1256             :         {
    1257      364817 :             mpPolygon->setPoint(nIndex, rValue);
    1258             :         }
    1259      368472 :     }
    1260             : 
    1261          30 :     void B2DPolygon::reserve(sal_uInt32 nCount)
    1262             :     {
    1263          30 :         mpPolygon->reserve(nCount);
    1264          30 :     }
    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      120581 :     void B2DPolygon::append(const B2DPoint& rPoint, sal_uInt32 nCount)
    1277             :     {
    1278      120581 :         if(nCount)
    1279             :         {
    1280      120581 :             mpPolygon->insert(mpPolygon->count(), rPoint, nCount);
    1281             :         }
    1282      120581 :     }
    1283             : 
    1284      374338 :     void B2DPolygon::append(const B2DPoint& rPoint)
    1285             :     {
    1286      374338 :         mpPolygon->append(rPoint);
    1287      374338 :     }
    1288             : 
    1289        8782 :     B2DPoint B2DPolygon::getPrevControlPoint(sal_uInt32 nIndex) const
    1290             :     {
    1291             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1292             : 
    1293        8782 :         if(mpPolygon->areControlPointsUsed())
    1294             :         {
    1295        8404 :             return mpPolygon->getPoint(nIndex) + mpPolygon->getPrevControlVector(nIndex);
    1296             :         }
    1297             :         else
    1298             :         {
    1299         378 :             return mpPolygon->getPoint(nIndex);
    1300             :         }
    1301             :     }
    1302             : 
    1303        8530 :     B2DPoint B2DPolygon::getNextControlPoint(sal_uInt32 nIndex) const
    1304             :     {
    1305             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1306             : 
    1307        8530 :         if(mpPolygon->areControlPointsUsed())
    1308             :         {
    1309        8176 :             return mpPolygon->getPoint(nIndex) + mpPolygon->getNextControlVector(nIndex);
    1310             :         }
    1311             :         else
    1312             :         {
    1313         354 :             return mpPolygon->getPoint(nIndex);
    1314             :         }
    1315             :     }
    1316             : 
    1317         198 :     void B2DPolygon::setPrevControlPoint(sal_uInt32 nIndex, const B2DPoint& rValue)
    1318             :     {
    1319             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1320         198 :         const basegfx::B2DVector aNewVector(rValue - mpPolygon->getPoint(nIndex));
    1321             : 
    1322         198 :         if(mpPolygon->getPrevControlVector(nIndex) != aNewVector)
    1323             :         {
    1324         198 :             mpPolygon->setPrevControlVector(nIndex, aNewVector);
    1325         198 :         }
    1326         198 :     }
    1327             : 
    1328          30 :     void B2DPolygon::setNextControlPoint(sal_uInt32 nIndex, const B2DPoint& rValue)
    1329             :     {
    1330             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1331          30 :         const basegfx::B2DVector aNewVector(rValue - mpPolygon->getPoint(nIndex));
    1332             : 
    1333          30 :         if(mpPolygon->getNextControlVector(nIndex) != aNewVector)
    1334             :         {
    1335          30 :             mpPolygon->setNextControlVector(nIndex, aNewVector);
    1336          30 :         }
    1337          30 :     }
    1338             : 
    1339           2 :     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           2 :         const B2DPoint aPoint(mpPolygon->getPoint(nIndex));
    1343           2 :         const basegfx::B2DVector aNewPrev(rPrev - aPoint);
    1344           2 :         const basegfx::B2DVector aNewNext(rNext - aPoint);
    1345             : 
    1346           2 :         if(mpPolygon->getPrevControlVector(nIndex) != aNewPrev || mpPolygon->getNextControlVector(nIndex) != aNewNext)
    1347             :         {
    1348           2 :             mpPolygon->setControlVectors(nIndex, aNewPrev, aNewNext);
    1349           2 :         }
    1350           2 :     }
    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           2 :     void B2DPolygon::resetControlPoints()
    1373             :     {
    1374           2 :         if(mpPolygon->areControlPointsUsed())
    1375             :         {
    1376           2 :             mpPolygon->resetControlVectors();
    1377             :         }
    1378           2 :     }
    1379             : 
    1380        4434 :     void B2DPolygon::appendBezierSegment(
    1381             :         const B2DPoint& rNextControlPoint,
    1382             :         const B2DPoint& rPrevControlPoint,
    1383             :         const B2DPoint& rPoint)
    1384             :     {
    1385        4434 :         const B2DVector aNewNextVector(mpPolygon->count() ? B2DVector(rNextControlPoint - mpPolygon->getPoint(mpPolygon->count() - 1)) : B2DVector::getEmptyVector());
    1386        4434 :         const B2DVector aNewPrevVector(rPrevControlPoint - rPoint);
    1387             : 
    1388        4434 :         if(aNewNextVector.equalZero() && aNewPrevVector.equalZero())
    1389             :         {
    1390          14 :             mpPolygon->insert(mpPolygon->count(), rPoint, 1);
    1391             :         }
    1392             :         else
    1393             :         {
    1394        4420 :             mpPolygon->appendBezierSegment(aNewNextVector, aNewPrevVector, rPoint);
    1395        4434 :         }
    1396        4434 :     }
    1397             : 
    1398      420494 :     bool B2DPolygon::areControlPointsUsed() const
    1399             :     {
    1400      420494 :         return mpPolygon->areControlPointsUsed();
    1401             :     }
    1402             : 
    1403         604 :     bool B2DPolygon::isPrevControlPointUsed(sal_uInt32 nIndex) const
    1404             :     {
    1405             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1406             : 
    1407         604 :         return (mpPolygon->areControlPointsUsed() && !mpPolygon->getPrevControlVector(nIndex).equalZero());
    1408             :     }
    1409             : 
    1410         362 :     bool B2DPolygon::isNextControlPointUsed(sal_uInt32 nIndex) const
    1411             :     {
    1412             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1413             : 
    1414         362 :         return (mpPolygon->areControlPointsUsed() && !mpPolygon->getNextControlVector(nIndex).equalZero());
    1415             :     }
    1416             : 
    1417        5046 :     B2VectorContinuity B2DPolygon::getContinuityInPoint(sal_uInt32 nIndex) const
    1418             :     {
    1419             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1420             : 
    1421        5046 :         if(mpPolygon->areControlPointsUsed())
    1422             :         {
    1423        5046 :             const B2DVector& rPrev(mpPolygon->getPrevControlVector(nIndex));
    1424        5046 :             const B2DVector& rNext(mpPolygon->getNextControlVector(nIndex));
    1425             : 
    1426        5046 :             return getContinuity(rPrev, rNext);
    1427             :         }
    1428             :         else
    1429             :         {
    1430           0 :             return CONTINUITY_NONE;
    1431             :         }
    1432             :     }
    1433             : 
    1434        2574 :     void B2DPolygon::getBezierSegment(sal_uInt32 nIndex, B2DCubicBezier& rTarget) const
    1435             :     {
    1436             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1437        2574 :         const bool bNextIndexValidWithoutClose(nIndex + 1 < mpPolygon->count());
    1438             : 
    1439        2574 :         if(bNextIndexValidWithoutClose || mpPolygon->isClosed())
    1440             :         {
    1441        2558 :             const sal_uInt32 nNextIndex(bNextIndexValidWithoutClose ? nIndex + 1 : 0);
    1442        2558 :             rTarget.setStartPoint(mpPolygon->getPoint(nIndex));
    1443        2558 :             rTarget.setEndPoint(mpPolygon->getPoint(nNextIndex));
    1444             : 
    1445        2558 :             if(mpPolygon->areControlPointsUsed())
    1446             :             {
    1447         218 :                 rTarget.setControlPointA(rTarget.getStartPoint() + mpPolygon->getNextControlVector(nIndex));
    1448         218 :                 rTarget.setControlPointB(rTarget.getEndPoint() + mpPolygon->getPrevControlVector(nNextIndex));
    1449             :             }
    1450             :             else
    1451             :             {
    1452             :                 // no bezier, reset control poins at rTarget
    1453        2340 :                 rTarget.setControlPointA(rTarget.getStartPoint());
    1454        2340 :                 rTarget.setControlPointB(rTarget.getEndPoint());
    1455             :             }
    1456             :         }
    1457             :         else
    1458             :         {
    1459             :             // no valid edge at all, reset rTarget to current point
    1460          16 :             const B2DPoint aPoint(mpPolygon->getPoint(nIndex));
    1461          16 :             rTarget.setStartPoint(aPoint);
    1462          16 :             rTarget.setEndPoint(aPoint);
    1463          16 :             rTarget.setControlPointA(aPoint);
    1464          16 :             rTarget.setControlPointB(aPoint);
    1465             :         }
    1466        2574 :     }
    1467             : 
    1468           0 :     B2DPolygon B2DPolygon::getDefaultAdaptiveSubdivision() const
    1469             :     {
    1470           0 :         return mpPolygon->getDefaultAdaptiveSubdivision(*this);
    1471             :     }
    1472             : 
    1473      196341 :     B2DRange B2DPolygon::getB2DRange() const
    1474             :     {
    1475      196341 :         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        2116 :     void B2DPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount)
    1501             :     {
    1502             :         OSL_ENSURE(nIndex + nCount <= mpPolygon->count(), "B2DPolygon Remove outside range (!)");
    1503             : 
    1504        2116 :         if(nCount)
    1505             :         {
    1506        2116 :             mpPolygon->remove(nIndex, nCount);
    1507             :         }
    1508        2116 :     }
    1509             : 
    1510        4732 :     void B2DPolygon::clear()
    1511             :     {
    1512        4732 :         mpPolygon = DefaultPolygon::get();
    1513        4732 :     }
    1514             : 
    1515      230256 :     bool B2DPolygon::isClosed() const
    1516             :     {
    1517      230256 :         return mpPolygon->isClosed();
    1518             :     }
    1519             : 
    1520      201284 :     void B2DPolygon::setClosed(bool bNew)
    1521             :     {
    1522      201284 :         if(isClosed() != bNew)
    1523             :         {
    1524      194495 :             mpPolygon->setClosed(bNew);
    1525             :         }
    1526      201284 :     }
    1527             : 
    1528         842 :     void B2DPolygon::flip()
    1529             :     {
    1530         842 :         if(count() > 1)
    1531             :         {
    1532         842 :             mpPolygon->flip();
    1533             :         }
    1534         842 :     }
    1535             : 
    1536         702 :     bool B2DPolygon::hasDoublePoints() const
    1537             :     {
    1538         702 :         return (mpPolygon->count() > 1 && mpPolygon->hasDoublePoints());
    1539             :     }
    1540             : 
    1541         256 :     void B2DPolygon::removeDoublePoints()
    1542             :     {
    1543         256 :         if(hasDoublePoints())
    1544             :         {
    1545          34 :             mpPolygon->removeDoublePointsAtBeginEnd();
    1546          34 :             mpPolygon->removeDoublePointsWholeTrack();
    1547             :         }
    1548         256 :     }
    1549             : 
    1550        8826 :     void B2DPolygon::transform(const B2DHomMatrix& rMatrix)
    1551             :     {
    1552        8826 :         if(mpPolygon->count() && !rMatrix.isIdentity())
    1553             :         {
    1554        6728 :             mpPolygon->transform(rMatrix);
    1555             :         }
    1556        8826 :     }
    1557             : 
    1558             : } // end of namespace basegfx
    1559             : 
    1560             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10