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

Generated by: LCOV version 1.11