LCOV - code coverage report
Current view: top level - basegfx/source/polygon - b2dpolygon.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 595 643 92.5 %
Date: 2014-11-03 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    95103056 : struct CoordinateData2D : public basegfx::B2DPoint
      33             : {
      34             : public:
      35           0 :     CoordinateData2D() {}
      36             : 
      37    15077203 :     explicit CoordinateData2D(const basegfx::B2DPoint& rData)
      38    15077203 :     :   B2DPoint(rData)
      39    15077203 :     {}
      40             : 
      41    12104480 :     CoordinateData2D& operator=(const basegfx::B2DPoint& rData)
      42             :     {
      43    12104480 :         B2DPoint::operator=(rData);
      44    12104480 :         return *this;
      45             :     }
      46             : 
      47     6477566 :     void transform(const basegfx::B2DHomMatrix& rMatrix)
      48             :     {
      49     6477566 :         *this *= rMatrix;
      50     6477566 :     }
      51             : };
      52             : 
      53     6126886 : class CoordinateDataArray2D
      54             : {
      55             :     typedef ::std::vector< CoordinateData2D > CoordinateData2DVector;
      56             : 
      57             :     CoordinateData2DVector                          maVector;
      58             : 
      59             : public:
      60         214 :     explicit CoordinateDataArray2D(sal_uInt32 nCount)
      61         214 :     :   maVector(nCount)
      62             :     {
      63         214 :     }
      64             : 
      65     6136226 :     explicit CoordinateDataArray2D(const CoordinateDataArray2D& rOriginal)
      66     6136226 :     :   maVector(rOriginal.maVector)
      67             :     {
      68     6136226 :     }
      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    20241803 :     sal_uInt32 count() const
      76             :     {
      77    20241803 :         return maVector.size();
      78             :     }
      79             : 
      80       45431 :     bool operator==(const CoordinateDataArray2D& rCandidate) const
      81             :     {
      82       45431 :         return (maVector == rCandidate.maVector);
      83             :     }
      84             : 
      85   147386339 :     const basegfx::B2DPoint& getCoordinate(sal_uInt32 nIndex) const
      86             :     {
      87   147386339 :         return maVector[nIndex];
      88             :     }
      89             : 
      90    12104480 :     void setCoordinate(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue)
      91             :     {
      92    12104480 :         maVector[nIndex] = rValue;
      93    12104480 :     }
      94             : 
      95       60314 :     void reserve(sal_uInt32 nCount)
      96             :     {
      97       60314 :         maVector.reserve(nCount);
      98       60314 :     }
      99             : 
     100    11566278 :     void append(const CoordinateData2D& rValue)
     101             :     {
     102    11566278 :         maVector.push_back(rValue);
     103    11566278 :     }
     104             : 
     105     3510925 :     void insert(sal_uInt32 nIndex, const CoordinateData2D& rValue, sal_uInt32 nCount)
     106             :     {
     107     3510925 :         if(nCount)
     108             :         {
     109             :             // add nCount copies of rValue
     110     3510925 :             CoordinateData2DVector::iterator aIndex(maVector.begin());
     111     3510925 :             aIndex += nIndex;
     112     3510925 :             maVector.insert(aIndex, nCount, rValue);
     113             :         }
     114     3510925 :     }
     115             : 
     116        4934 :     void insert(sal_uInt32 nIndex, const CoordinateDataArray2D& rSource)
     117             :     {
     118        4934 :         const sal_uInt32 nCount(rSource.maVector.size());
     119             : 
     120        4934 :         if(nCount)
     121             :         {
     122             :             // insert data
     123        4934 :             CoordinateData2DVector::iterator aIndex(maVector.begin());
     124        4934 :             aIndex += nIndex;
     125        4934 :             CoordinateData2DVector::const_iterator aStart(rSource.maVector.begin());
     126        4934 :             CoordinateData2DVector::const_iterator aEnd(rSource.maVector.end());
     127        4934 :             maVector.insert(aIndex, aStart, aEnd);
     128             :         }
     129        4934 :     }
     130             : 
     131       61069 :     void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
     132             :     {
     133       61069 :         if(nCount)
     134             :         {
     135             :             // remove point data
     136       61069 :             CoordinateData2DVector::iterator aStart(maVector.begin());
     137       61069 :             aStart += nIndex;
     138       61069 :             const CoordinateData2DVector::iterator aEnd(aStart + nCount);
     139       61069 :             maVector.erase(aStart, aEnd);
     140             :         }
     141       61069 :     }
     142             : 
     143         765 :     void flip(bool bIsClosed)
     144             :     {
     145         765 :         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         765 :             const sal_uInt32 nHalfSize(bIsClosed ? (maVector.size() - 1) >> 1 : maVector.size() >> 1);
     150         765 :             CoordinateData2DVector::iterator aStart(bIsClosed ? maVector.begin() + 1 : maVector.begin());
     151         765 :             CoordinateData2DVector::iterator aEnd(maVector.end() - 1);
     152             : 
     153        2206 :             for(sal_uInt32 a(0); a < nHalfSize; a++)
     154             :             {
     155        1441 :                 ::std::swap(*aStart, *aEnd);
     156        1441 :                 ++aStart;
     157        1441 :                 --aEnd;
     158             :             }
     159             :         }
     160         765 :     }
     161             : 
     162         722 :     void removeDoublePointsAtBeginEnd()
     163             :     {
     164             :         // remove from end as long as there are at least two points
     165             :         // and begin/end are equal
     166        2021 :         while((maVector.size() > 1) && (maVector[0] == maVector[maVector.size() - 1]))
     167             :         {
     168         577 :             maVector.pop_back();
     169             :         }
     170         722 :     }
     171             : 
     172        1375 :     void removeDoublePointsWholeTrack()
     173             :     {
     174        1375 :         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       32018 :         while((maVector.size() > 1) && (nIndex <= maVector.size() - 2))
     179             :         {
     180       29268 :             if(maVector[nIndex] == maVector[nIndex + 1])
     181             :             {
     182             :                 // if next is same as index, delete next
     183        1854 :                 maVector.erase(maVector.begin() + (nIndex + 1));
     184             :             }
     185             :             else
     186             :             {
     187             :                 // if different, step forward
     188       27414 :                 nIndex++;
     189             :             }
     190             :         }
     191        1375 :     }
     192             : 
     193      801007 :     void transform(const basegfx::B2DHomMatrix& rMatrix)
     194             :     {
     195      801007 :         CoordinateData2DVector::iterator aStart(maVector.begin());
     196      801007 :         CoordinateData2DVector::iterator aEnd(maVector.end());
     197             : 
     198     7278573 :         for(; aStart != aEnd; ++aStart)
     199             :         {
     200     6477566 :             aStart->transform(rMatrix);
     201             :         }
     202      801007 :     }
     203             : };
     204             : 
     205     2196561 : class ControlVectorPair2D
     206             : {
     207             :     basegfx::B2DVector                          maPrevVector;
     208             :     basegfx::B2DVector                          maNextVector;
     209             : 
     210             : public:
     211      242115 :     explicit ControlVectorPair2D() {}
     212             : 
     213     2800056 :     const basegfx::B2DVector& getPrevVector() const
     214             :     {
     215     2800056 :         return maPrevVector;
     216             :     }
     217             : 
     218      449960 :     void setPrevVector(const basegfx::B2DVector& rValue)
     219             :     {
     220      449960 :         if(rValue != maPrevVector)
     221      380182 :             maPrevVector = rValue;
     222      449960 :     }
     223             : 
     224     2733835 :     const basegfx::B2DVector& getNextVector() const
     225             :     {
     226     2733835 :         return maNextVector;
     227             :     }
     228             : 
     229      442392 :     void setNextVector(const basegfx::B2DVector& rValue)
     230             :     {
     231      442392 :         if(rValue != maNextVector)
     232      372430 :             maNextVector = rValue;
     233      442392 :     }
     234             : 
     235        6287 :     bool operator==(const ControlVectorPair2D& rData) const
     236             :     {
     237        6287 :         return (maPrevVector == rData.getPrevVector() && maNextVector == rData.getNextVector());
     238             :     }
     239             : 
     240         602 :     void flip()
     241             :     {
     242         602 :         ::std::swap(maPrevVector, maNextVector);
     243         602 :     }
     244             : };
     245             : 
     246      152941 : class ControlVectorArray2D
     247             : {
     248             :     typedef ::std::vector< ControlVectorPair2D > ControlVectorPair2DVector;
     249             : 
     250             :     ControlVectorPair2DVector                           maVector;
     251             :     sal_uInt32                                          mnUsedVectors;
     252             : 
     253             : public:
     254       30203 :     explicit ControlVectorArray2D(sal_uInt32 nCount)
     255             :     :   maVector(nCount),
     256       30203 :         mnUsedVectors(0)
     257       30203 :     {}
     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        1449 :     bool operator==(const ControlVectorArray2D& rCandidate) const
     282             :     {
     283        1449 :         return (maVector == rCandidate.maVector);
     284             :     }
     285             : 
     286     3362600 :     bool isUsed() const
     287             :     {
     288     3362600 :         return (0 != mnUsedVectors);
     289             :     }
     290             : 
     291     2124745 :     const basegfx::B2DVector& getPrevVector(sal_uInt32 nIndex) const
     292             :     {
     293     2124745 :         return maVector[nIndex].getPrevVector();
     294             :     }
     295             : 
     296      452160 :     void setPrevVector(sal_uInt32 nIndex, const basegfx::B2DVector& rValue)
     297             :     {
     298      452160 :         bool bWasUsed(mnUsedVectors && !maVector[nIndex].getPrevVector().equalZero());
     299      452160 :         bool bIsUsed(!rValue.equalZero());
     300             : 
     301      452160 :         if(bWasUsed)
     302             :         {
     303      318455 :             if(bIsUsed)
     304             :             {
     305      318435 :                 maVector[nIndex].setPrevVector(rValue);
     306             :             }
     307             :             else
     308             :             {
     309          20 :                 maVector[nIndex].setPrevVector(basegfx::B2DVector::getEmptyVector());
     310          20 :                 mnUsedVectors--;
     311             :             }
     312             :         }
     313             :         else
     314             :         {
     315      133705 :             if(bIsUsed)
     316             :             {
     317      131505 :                 maVector[nIndex].setPrevVector(rValue);
     318      131505 :                 mnUsedVectors++;
     319             :             }
     320             :         }
     321      452160 :     }
     322             : 
     323     2094096 :     const basegfx::B2DVector& getNextVector(sal_uInt32 nIndex) const
     324             :     {
     325     2094096 :         return maVector[nIndex].getNextVector();
     326             :     }
     327             : 
     328      443999 :     void setNextVector(sal_uInt32 nIndex, const basegfx::B2DVector& rValue)
     329             :     {
     330      443999 :         bool bWasUsed(mnUsedVectors && !maVector[nIndex].getNextVector().equalZero());
     331      443999 :         bool bIsUsed(!rValue.equalZero());
     332             : 
     333      443999 :         if(bWasUsed)
     334             :         {
     335      318578 :             if(bIsUsed)
     336             :             {
     337      318578 :                 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      125421 :             if(bIsUsed)
     348             :             {
     349      123814 :                 maVector[nIndex].setNextVector(rValue);
     350      123814 :                 mnUsedVectors++;
     351             :             }
     352             :         }
     353      443999 :     }
     354             : 
     355       76086 :     void append(const ControlVectorPair2D& rValue)
     356             :     {
     357       76086 :         maVector.push_back(rValue);
     358             : 
     359       76086 :         if(!rValue.getPrevVector().equalZero())
     360           0 :             mnUsedVectors += 1;
     361             : 
     362       76086 :         if(!rValue.getNextVector().equalZero())
     363           0 :             mnUsedVectors += 1;
     364       76086 :     }
     365             : 
     366      124448 :     void insert(sal_uInt32 nIndex, const ControlVectorPair2D& rValue, sal_uInt32 nCount)
     367             :     {
     368      124448 :         if(nCount)
     369             :         {
     370             :             // add nCount copies of rValue
     371      124448 :             ControlVectorPair2DVector::iterator aIndex(maVector.begin());
     372      124448 :             aIndex += nIndex;
     373      124448 :             maVector.insert(aIndex, nCount, rValue);
     374             : 
     375      124448 :             if(!rValue.getPrevVector().equalZero())
     376           0 :                 mnUsedVectors += nCount;
     377             : 
     378      124448 :             if(!rValue.getNextVector().equalZero())
     379           0 :                 mnUsedVectors += nCount;
     380             :         }
     381      124448 :     }
     382             : 
     383         295 :     void insert(sal_uInt32 nIndex, const ControlVectorArray2D& rSource)
     384             :     {
     385         295 :         const sal_uInt32 nCount(rSource.maVector.size());
     386             : 
     387         295 :         if(nCount)
     388             :         {
     389             :             // insert data
     390         295 :             ControlVectorPair2DVector::iterator aIndex(maVector.begin());
     391         295 :             aIndex += nIndex;
     392         295 :             ControlVectorPair2DVector::const_iterator aStart(rSource.maVector.begin());
     393         295 :             ControlVectorPair2DVector::const_iterator aEnd(rSource.maVector.end());
     394         295 :             maVector.insert(aIndex, aStart, aEnd);
     395             : 
     396        2002 :             for(; aStart != aEnd; ++aStart)
     397             :             {
     398        1707 :                 if(!aStart->getPrevVector().equalZero())
     399        1376 :                     mnUsedVectors++;
     400             : 
     401        1707 :                 if(!aStart->getNextVector().equalZero())
     402        1376 :                     mnUsedVectors++;
     403             :             }
     404             :         }
     405         295 :     }
     406             : 
     407       15912 :     void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
     408             :     {
     409       15912 :         if(nCount)
     410             :         {
     411       15912 :             const ControlVectorPair2DVector::iterator aDeleteStart(maVector.begin() + nIndex);
     412       15912 :             const ControlVectorPair2DVector::iterator aDeleteEnd(aDeleteStart + nCount);
     413       15912 :             ControlVectorPair2DVector::const_iterator aStart(aDeleteStart);
     414             : 
     415       31860 :             for(; mnUsedVectors && aStart != aDeleteEnd; ++aStart)
     416             :             {
     417       15948 :                 if(!aStart->getPrevVector().equalZero())
     418        7352 :                     mnUsedVectors--;
     419             : 
     420       15948 :                 if(mnUsedVectors && !aStart->getNextVector().equalZero())
     421           2 :                     mnUsedVectors--;
     422             :             }
     423             : 
     424             :             // remove point data
     425       15912 :             maVector.erase(aDeleteStart, aDeleteEnd);
     426             :         }
     427       15912 :     }
     428             : 
     429         104 :     void flip(bool bIsClosed)
     430             :     {
     431         104 :         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         104 :             const sal_uInt32 nHalfSize(bIsClosed ? (maVector.size() - 1) >> 1 : maVector.size() >> 1);
     436         104 :             ControlVectorPair2DVector::iterator aStart(bIsClosed ? maVector.begin() + 1 : maVector.begin());
     437         104 :             ControlVectorPair2DVector::iterator aEnd(maVector.end() - 1);
     438             : 
     439         378 :             for(sal_uInt32 a(0); a < nHalfSize; a++)
     440             :             {
     441             :                 // swap Prev and Next
     442         274 :                 aStart->flip();
     443         274 :                 aEnd->flip();
     444             : 
     445             :                 // swap entries
     446         274 :                 ::std::swap(*aStart, *aEnd);
     447             : 
     448         274 :                 ++aStart;
     449         274 :                 --aEnd;
     450             :             }
     451             : 
     452         104 :             if(aStart == aEnd)
     453             :             {
     454             :                 // swap Prev and Next at middle element (if exists)
     455          52 :                 aStart->flip();
     456             :             }
     457             : 
     458         104 :             if(bIsClosed)
     459             :             {
     460             :                 // swap Prev and Next at start element
     461           2 :                 maVector.begin()->flip();
     462             :             }
     463             :         }
     464         104 :     }
     465             : };
     466             : 
     467     5088723 : 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     5092322 :     ImplBufferedData()
     478             :     :   mpDefaultSubdivision(),
     479     5092322 :         mpB2DRange()
     480     5092322 :     {}
     481             : 
     482        5421 :     const basegfx::B2DPolygon& getDefaultAdaptiveSubdivision(const basegfx::B2DPolygon& rSource) const
     483             :     {
     484        5421 :         if(!mpDefaultSubdivision)
     485             :         {
     486        2591 :             const_cast< ImplBufferedData* >(this)->mpDefaultSubdivision.reset(new basegfx::B2DPolygon(basegfx::tools::adaptiveSubdivideByCount(rSource, 9)));
     487             :         }
     488             : 
     489        5421 :         return *mpDefaultSubdivision;
     490             :     }
     491             : 
     492     5579166 :     const basegfx::B2DRange& getB2DRange(const basegfx::B2DPolygon& rSource) const
     493             :     {
     494     5579166 :         if(!mpB2DRange)
     495             :         {
     496     5092247 :             basegfx::B2DRange aNewRange;
     497     5092247 :             const sal_uInt32 nPointCount(rSource.count());
     498             : 
     499     5092247 :             if(nPointCount)
     500             :             {
     501    29151390 :                 for(sal_uInt32 a(0); a < nPointCount; a++)
     502             :                 {
     503    24059143 :                     aNewRange.expand(rSource.getB2DPoint(a));
     504             :                 }
     505             : 
     506     5092247 :                 if(rSource.areControlPointsUsed())
     507             :                 {
     508       41315 :                     const sal_uInt32 nEdgeCount(rSource.isClosed() ? nPointCount : nPointCount - 1);
     509             : 
     510       41315 :                     if(nEdgeCount)
     511             :                     {
     512       41315 :                         basegfx::B2DCubicBezier aEdge;
     513       41315 :                         aEdge.setStartPoint(rSource.getB2DPoint(0));
     514             : 
     515      330047 :                         for(sal_uInt32 b(0); b < nEdgeCount; b++)
     516             :                         {
     517      288732 :                             const sal_uInt32 nNextIndex((b + 1) % nPointCount);
     518      288732 :                             aEdge.setControlPointA(rSource.getNextControlPoint(b));
     519      288732 :                             aEdge.setControlPointB(rSource.getPrevControlPoint(nNextIndex));
     520      288732 :                             aEdge.setEndPoint(rSource.getB2DPoint(nNextIndex));
     521             : 
     522      288732 :                             if(aEdge.isBezier())
     523             :                             {
     524      152492 :                                 const basegfx::B2DRange aBezierRangeWithControlPoints(aEdge.getRange());
     525             : 
     526      152492 :                                 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       23993 :                                     ::std::vector< double > aExtremas;
     534             : 
     535       23993 :                                     aExtremas.reserve(4);
     536       23993 :                                     aEdge.getAllExtremumPositions(aExtremas);
     537             : 
     538       23993 :                                     const sal_uInt32 nExtremaCount(aExtremas.size());
     539             : 
     540       47383 :                                     for(sal_uInt32 c(0); c < nExtremaCount; c++)
     541             :                                     {
     542       23390 :                                         aNewRange.expand(aEdge.interpolatePoint(aExtremas[c]));
     543       23993 :                                     }
     544             :                                 }
     545             :                             }
     546             : 
     547             :                             // prepare next edge
     548      288732 :                             aEdge.setStartPoint(aEdge.getEndPoint());
     549       41315 :                         }
     550             :                     }
     551             :                 }
     552             :             }
     553             : 
     554     5092247 :             const_cast< ImplBufferedData* >(this)->mpB2DRange.reset(new basegfx::B2DRange(aNewRange));
     555             :         }
     556             : 
     557     5579166 :         return *mpB2DRange;
     558             :     }
     559             : };
     560             : 
     561     6126886 : 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        5471 :     const basegfx::B2DPolygon& getDefaultAdaptiveSubdivision(const basegfx::B2DPolygon& rSource) const
     580             :     {
     581        5471 :         if(!mpControlVector || !mpControlVector->isUsed())
     582             :         {
     583          50 :             return rSource;
     584             :         }
     585             : 
     586        5421 :         if(!mpBufferedData)
     587             :         {
     588         556 :             const_cast< ImplB2DPolygon* >(this)->mpBufferedData.reset(new ImplBufferedData);
     589             :         }
     590             : 
     591        5421 :         return mpBufferedData->getDefaultAdaptiveSubdivision(rSource);
     592             :     }
     593             : 
     594     5579166 :     const basegfx::B2DRange& getB2DRange(const basegfx::B2DPolygon& rSource) const
     595             :     {
     596     5579166 :         if(!mpBufferedData)
     597             :         {
     598     5091766 :             const_cast< ImplB2DPolygon* >(this)->mpBufferedData.reset(new ImplBufferedData);
     599             :         }
     600             : 
     601     5579166 :         return mpBufferedData->getB2DRange(rSource);
     602             :     }
     603             : 
     604         214 :     ImplB2DPolygon()
     605             :     :   maPoints(0),
     606             :         mpControlVector(),
     607             :         mpBufferedData(),
     608         214 :         mbIsClosed(false)
     609         214 :     {}
     610             : 
     611     6136226 :     ImplB2DPolygon(const ImplB2DPolygon& rToBeCopied)
     612             :     :   maPoints(rToBeCopied.maPoints),
     613             :         mpControlVector(),
     614             :         mpBufferedData(),
     615     6136226 :         mbIsClosed(rToBeCopied.mbIsClosed)
     616             :     {
     617             :         // complete initialization using copy
     618     6136226 :         if(rToBeCopied.mpControlVector && rToBeCopied.mpControlVector->isUsed())
     619             :         {
     620       61388 :             mpControlVector.reset( new ControlVectorArray2D(*rToBeCopied.mpControlVector) );
     621             :         }
     622     6136226 :     }
     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    19335397 :     sal_uInt32 count() const
     643             :     {
     644    19335397 :         return maPoints.count();
     645             :     }
     646             : 
     647     6321963 :     bool isClosed() const
     648             :     {
     649     6321963 :         return mbIsClosed;
     650             :     }
     651             : 
     652     4916775 :     void setClosed(bool bNew)
     653             :     {
     654     4916775 :         if(bNew != mbIsClosed)
     655             :         {
     656     4916775 :             mpBufferedData.reset();
     657     4916775 :             mbIsClosed = bNew;
     658             :         }
     659     4916775 :     }
     660             : 
     661       47887 :     bool operator==(const ImplB2DPolygon& rCandidate) const
     662             :     {
     663       47887 :         if(mbIsClosed == rCandidate.mbIsClosed)
     664             :         {
     665       45431 :             if(maPoints == rCandidate.maPoints)
     666             :             {
     667       26985 :                 bool bControlVectorsAreEqual(true);
     668             : 
     669       26985 :                 if(mpControlVector)
     670             :                 {
     671        1449 :                     if(rCandidate.mpControlVector)
     672             :                     {
     673        1449 :                         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       25536 :                     if(rCandidate.mpControlVector)
     684             :                     {
     685             :                         // we have no control vector, so it's assumed all unused.
     686          56 :                         bControlVectorsAreEqual = !rCandidate.mpControlVector->isUsed();
     687             :                     }
     688             :                 }
     689             : 
     690       26985 :                 if(bControlVectorsAreEqual)
     691             :                 {
     692       26929 :                     return true;
     693             :                 }
     694             :             }
     695             :         }
     696             : 
     697       20958 :         return false;
     698             :     }
     699             : 
     700   146680518 :     const basegfx::B2DPoint& getPoint(sal_uInt32 nIndex) const
     701             :     {
     702   146680518 :         return maPoints.getCoordinate(nIndex);
     703             :     }
     704             : 
     705    11594941 :     void setPoint(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue)
     706             :     {
     707    11594941 :         mpBufferedData.reset();
     708    11594941 :         maPoints.setCoordinate(nIndex, rValue);
     709    11594941 :     }
     710             : 
     711       60314 :     void reserve(sal_uInt32 nCount)
     712             :     {
     713       60314 :         maPoints.reserve(nCount);
     714       60314 :     }
     715             : 
     716    11566278 :     void append(const basegfx::B2DPoint& rPoint)
     717             :     {
     718    11566278 :         mpBufferedData.reset(); // TODO: is this needed?
     719    11566278 :         const CoordinateData2D aCoordinate(rPoint);
     720    11566278 :         maPoints.append(aCoordinate);
     721             : 
     722    11566278 :         if(mpControlVector)
     723             :         {
     724       76086 :             const ControlVectorPair2D aVectorPair;
     725       76086 :             mpControlVector->append(aVectorPair);
     726    11566278 :         }
     727    11566278 :     }
     728             : 
     729     3510925 :     void insert(sal_uInt32 nIndex, const basegfx::B2DPoint& rPoint, sal_uInt32 nCount)
     730             :     {
     731     3510925 :         if(nCount)
     732             :         {
     733     3510925 :             mpBufferedData.reset();
     734     3510925 :             CoordinateData2D aCoordinate(rPoint);
     735     3510925 :             maPoints.insert(nIndex, aCoordinate, nCount);
     736             : 
     737     3510925 :             if(mpControlVector)
     738             :             {
     739      124440 :                 ControlVectorPair2D aVectorPair;
     740      124440 :                 mpControlVector->insert(nIndex, aVectorPair, nCount);
     741     3510925 :             }
     742             :         }
     743     3510925 :     }
     744             : 
     745     1598707 :     const basegfx::B2DVector& getPrevControlVector(sal_uInt32 nIndex) const
     746             :     {
     747     1598707 :         if(mpControlVector)
     748             :         {
     749     1598292 :             return mpControlVector->getPrevVector(nIndex);
     750             :         }
     751             :         else
     752             :         {
     753         415 :             return basegfx::B2DVector::getEmptyVector();
     754             :         }
     755             :     }
     756             : 
     757      135761 :     void setPrevControlVector(sal_uInt32 nIndex, const basegfx::B2DVector& rValue)
     758             :     {
     759      135761 :         if(!mpControlVector)
     760             :         {
     761        1327 :             if(!rValue.equalZero())
     762             :             {
     763        1325 :                 mpBufferedData.reset();
     764        1325 :                 mpControlVector.reset( new ControlVectorArray2D(maPoints.count()) );
     765        1325 :                 mpControlVector->setPrevVector(nIndex, rValue);
     766             :             }
     767             :         }
     768             :         else
     769             :         {
     770      134434 :             mpBufferedData.reset();
     771      134434 :             mpControlVector->setPrevVector(nIndex, rValue);
     772             : 
     773      134434 :             if(!mpControlVector->isUsed())
     774           0 :                 mpControlVector.reset();
     775             :         }
     776      135761 :     }
     777             : 
     778     1575737 :     const basegfx::B2DVector& getNextControlVector(sal_uInt32 nIndex) const
     779             :     {
     780     1575737 :         if(mpControlVector)
     781             :         {
     782     1575570 :             return mpControlVector->getNextVector(nIndex);
     783             :         }
     784             :         else
     785             :         {
     786         167 :             return basegfx::B2DVector::getEmptyVector();
     787             :         }
     788             :     }
     789             : 
     790      131093 :     void setNextControlVector(sal_uInt32 nIndex, const basegfx::B2DVector& rValue)
     791             :     {
     792      131093 :         if(!mpControlVector)
     793             :         {
     794       29646 :             if(!rValue.equalZero())
     795             :             {
     796       28736 :                 mpBufferedData.reset();
     797       28736 :                 mpControlVector.reset( new ControlVectorArray2D(maPoints.count()) );
     798       28736 :                 mpControlVector->setNextVector(nIndex, rValue);
     799             :             }
     800             :         }
     801             :         else
     802             :         {
     803      101447 :             mpBufferedData.reset();
     804      101447 :             mpControlVector->setNextVector(nIndex, rValue);
     805             : 
     806      101447 :             if(!mpControlVector->isUsed())
     807           0 :                 mpControlVector.reset();
     808             :         }
     809      131093 :     }
     810             : 
     811    14913840 :     bool areControlPointsUsed() const
     812             :     {
     813    14913840 :         return (mpControlVector && mpControlVector->isUsed());
     814             :     }
     815             : 
     816           2 :     void resetControlVectors()
     817             :     {
     818           2 :         mpBufferedData.reset();
     819           2 :         mpControlVector.reset();
     820           2 :     }
     821             : 
     822           2 :     void setControlVectors(sal_uInt32 nIndex, const basegfx::B2DVector& rPrev, const basegfx::B2DVector& rNext)
     823             :     {
     824           2 :         setPrevControlVector(nIndex, rPrev);
     825           2 :         setNextControlVector(nIndex, rNext);
     826           2 :     }
     827             : 
     828      123882 :     void appendBezierSegment(const basegfx::B2DVector& rNext, const basegfx::B2DVector& rPrev, const basegfx::B2DPoint& rPoint)
     829             :     {
     830      123882 :         mpBufferedData.reset();
     831      123882 :         const sal_uInt32 nCount(maPoints.count());
     832             : 
     833      123882 :         if(nCount)
     834             :         {
     835      123880 :             setNextControlVector(nCount - 1, rNext);
     836             :         }
     837             : 
     838      123882 :         insert(nCount, rPoint, 1);
     839      123882 :         setPrevControlVector(nCount, rPrev);
     840      123882 :     }
     841             : 
     842        4934 :     void insert(sal_uInt32 nIndex, const ImplB2DPolygon& rSource)
     843             :     {
     844        4934 :         const sal_uInt32 nCount(rSource.maPoints.count());
     845             : 
     846        4934 :         if(nCount)
     847             :         {
     848        4934 :             mpBufferedData.reset();
     849             : 
     850        4934 :             if(rSource.mpControlVector && rSource.mpControlVector->isUsed() && !mpControlVector)
     851             :             {
     852         142 :                 mpControlVector.reset( new ControlVectorArray2D(maPoints.count()) );
     853             :             }
     854             : 
     855        4934 :             maPoints.insert(nIndex, rSource.maPoints);
     856             : 
     857        4934 :             if(rSource.mpControlVector)
     858             :             {
     859         295 :                 mpControlVector->insert(nIndex, *rSource.mpControlVector);
     860             : 
     861         295 :                 if(!mpControlVector->isUsed())
     862           0 :                     mpControlVector.reset();
     863             :             }
     864        4639 :             else if(mpControlVector)
     865             :             {
     866           8 :                 ControlVectorPair2D aVectorPair;
     867           8 :                 mpControlVector->insert(nIndex, aVectorPair, nCount);
     868             :             }
     869             :         }
     870        4934 :     }
     871             : 
     872       61069 :     void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
     873             :     {
     874       61069 :         if(nCount)
     875             :         {
     876       61069 :             mpBufferedData.reset();
     877       61069 :             maPoints.remove(nIndex, nCount);
     878             : 
     879       61069 :             if(mpControlVector)
     880             :             {
     881       15912 :                 mpControlVector->remove(nIndex, nCount);
     882             : 
     883       15912 :                 if(!mpControlVector->isUsed())
     884           0 :                     mpControlVector.reset();
     885             :             }
     886             :         }
     887       61069 :     }
     888             : 
     889         765 :     void flip()
     890             :     {
     891         765 :         if(maPoints.count() > 1)
     892             :         {
     893         765 :             mpBufferedData.reset();
     894             : 
     895             :             // flip points
     896         765 :             maPoints.flip(mbIsClosed);
     897             : 
     898         765 :             if(mpControlVector)
     899             :             {
     900             :                 // flip control vector
     901         104 :                 mpControlVector->flip(mbIsClosed);
     902             :             }
     903             :         }
     904         765 :     }
     905             : 
     906       32017 :     bool hasDoublePoints() const
     907             :     {
     908       32017 :         if(mbIsClosed)
     909             :         {
     910             :             // check for same start and end point
     911        9156 :             const sal_uInt32 nIndex(maPoints.count() - 1);
     912             : 
     913        9156 :             if(maPoints.getCoordinate(0) == maPoints.getCoordinate(nIndex))
     914             :             {
     915        3190 :                 if(mpControlVector)
     916             :                 {
     917        2667 :                     if(mpControlVector->getNextVector(nIndex).equalZero() && mpControlVector->getPrevVector(0).equalZero())
     918             :                     {
     919        2667 :                         return true;
     920             :                     }
     921             :                 }
     922             :                 else
     923             :                 {
     924         523 :                     return true;
     925             :                 }
     926             :             }
     927             :         }
     928             : 
     929             :         // test for range
     930       84305 :         for(sal_uInt32 a(0); a < maPoints.count() - 1; a++)
     931             :         {
     932       57535 :             if(maPoints.getCoordinate(a) == maPoints.getCoordinate(a + 1))
     933             :             {
     934        2063 :                 if(mpControlVector)
     935             :                 {
     936        1106 :                     if(mpControlVector->getNextVector(a).equalZero() && mpControlVector->getPrevVector(a + 1).equalZero())
     937             :                     {
     938        1100 :                         return true;
     939             :                     }
     940             :                 }
     941             :                 else
     942             :                 {
     943         957 :                     return true;
     944             :                 }
     945             :             }
     946             :         }
     947             : 
     948       26770 :         return false;
     949             :     }
     950             : 
     951        4683 :     void removeDoublePointsAtBeginEnd()
     952             :     {
     953             :         // Only remove DoublePoints at Begin and End when poly is closed
     954        4683 :         if(mbIsClosed)
     955             :         {
     956        3004 :             mpBufferedData.reset();
     957             : 
     958        3004 :             if(mpControlVector)
     959             :             {
     960             :                 bool bRemove;
     961             : 
     962        5314 :                 do
     963             :                 {
     964        5314 :                     bRemove = false;
     965             : 
     966        5314 :                     if(maPoints.count() > 1)
     967             :                     {
     968        5314 :                         const sal_uInt32 nIndex(maPoints.count() - 1);
     969             : 
     970        5314 :                         if(maPoints.getCoordinate(0) == maPoints.getCoordinate(nIndex))
     971             :                         {
     972        3034 :                             if(mpControlVector)
     973             :                             {
     974        3034 :                                 if(mpControlVector->getNextVector(nIndex).equalZero() && mpControlVector->getPrevVector(0).equalZero())
     975             :                                 {
     976        3032 :                                     bRemove = true;
     977             :                                 }
     978             :                             }
     979             :                             else
     980             :                             {
     981           0 :                                 bRemove = true;
     982             :                             }
     983             :                         }
     984             :                     }
     985             : 
     986        5314 :                     if(bRemove)
     987             :                     {
     988        3032 :                         const sal_uInt32 nIndex(maPoints.count() - 1);
     989             : 
     990        3032 :                         if(mpControlVector && !mpControlVector->getPrevVector(nIndex).equalZero())
     991             :                         {
     992        1309 :                             mpControlVector->setPrevVector(0, mpControlVector->getPrevVector(nIndex));
     993             :                         }
     994             : 
     995        3032 :                         remove(nIndex, 1);
     996             :                     }
     997             :                 }
     998             :                 while(bRemove);
     999             :             }
    1000             :             else
    1001             :             {
    1002         722 :                 maPoints.removeDoublePointsAtBeginEnd();
    1003             :             }
    1004             :         }
    1005        4683 :     }
    1006             : 
    1007        4683 :     void removeDoublePointsWholeTrack()
    1008             :     {
    1009        4683 :         mpBufferedData.reset();
    1010             : 
    1011        4683 :         if(mpControlVector)
    1012             :         {
    1013        3308 :             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       32752 :             while((maPoints.count() > 1) && (nIndex <= maPoints.count() - 2))
    1018             :             {
    1019       26136 :                 bool bRemove(maPoints.getCoordinate(nIndex) == maPoints.getCoordinate(nIndex + 1));
    1020             : 
    1021       26136 :                 if(bRemove)
    1022             :                 {
    1023        2180 :                     if(mpControlVector)
    1024             :                     {
    1025        2180 :                         if(!mpControlVector->getNextVector(nIndex).equalZero() || !mpControlVector->getPrevVector(nIndex + 1).equalZero())
    1026             :                         {
    1027           3 :                             bRemove = false;
    1028             :                         }
    1029             :                     }
    1030             :                 }
    1031             : 
    1032       26136 :                 if(bRemove)
    1033             :                 {
    1034        2177 :                     if(mpControlVector && !mpControlVector->getPrevVector(nIndex).equalZero())
    1035             :                     {
    1036        1420 :                         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        2177 :                     remove(nIndex, 1);
    1041             :                 }
    1042             :                 else
    1043             :                 {
    1044             :                     // if different, step forward
    1045       23959 :                     nIndex++;
    1046             :                 }
    1047             :             }
    1048             :         }
    1049             :         else
    1050             :         {
    1051        1375 :             maPoints.removeDoublePointsWholeTrack();
    1052             :         }
    1053        4683 :     }
    1054             : 
    1055      872081 :     void transform(const basegfx::B2DHomMatrix& rMatrix)
    1056             :     {
    1057      872081 :         mpBufferedData.reset();
    1058             : 
    1059      872081 :         if(mpControlVector)
    1060             :         {
    1061      580613 :             for(sal_uInt32 a(0); a < maPoints.count(); a++)
    1062             :             {
    1063      509539 :                 basegfx::B2DPoint aCandidate = maPoints.getCoordinate(a);
    1064             : 
    1065      509539 :                 if(mpControlVector->isUsed())
    1066             :                 {
    1067      509539 :                     const basegfx::B2DVector& rPrevVector(mpControlVector->getPrevVector(a));
    1068      509539 :                     const basegfx::B2DVector& rNextVector(mpControlVector->getNextVector(a));
    1069             : 
    1070      509539 :                     if(!rPrevVector.equalZero())
    1071             :                     {
    1072      313672 :                         basegfx::B2DVector aPrevVector(rMatrix * rPrevVector);
    1073      313672 :                         mpControlVector->setPrevVector(a, aPrevVector);
    1074             :                     }
    1075             : 
    1076      509539 :                     if(!rNextVector.equalZero())
    1077             :                     {
    1078      313816 :                         basegfx::B2DVector aNextVector(rMatrix * rNextVector);
    1079      313816 :                         mpControlVector->setNextVector(a, aNextVector);
    1080             :                     }
    1081             :                 }
    1082             : 
    1083      509539 :                 aCandidate *= rMatrix;
    1084      509539 :                 maPoints.setCoordinate(a, aCandidate);
    1085      509539 :             }
    1086             : 
    1087       71074 :             if(!mpControlVector->isUsed())
    1088           0 :                 mpControlVector.reset();
    1089             :         }
    1090             :         else
    1091             :         {
    1092      801007 :             maPoints.transform(rMatrix);
    1093             :         }
    1094      872081 :     }
    1095             : };
    1096             : 
    1097             : namespace basegfx
    1098             : {
    1099             :     namespace
    1100             :     {
    1101             :         struct DefaultPolygon: public rtl::Static<B2DPolygon::ImplType, DefaultPolygon> {};
    1102             :     }
    1103             : 
    1104     5359855 :     B2DPolygon::B2DPolygon()
    1105     5359855 :     :   mpPolygon(DefaultPolygon::get())
    1106     5359855 :     {}
    1107             : 
    1108    21997601 :     B2DPolygon::B2DPolygon(const B2DPolygon& rPolygon)
    1109    21997601 :     :   mpPolygon(rPolygon.mpPolygon)
    1110    21997601 :     {}
    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    27346550 :     B2DPolygon::~B2DPolygon()
    1121             :     {
    1122    27346550 :     }
    1123             : 
    1124       84180 :     B2DPolygon& B2DPolygon::operator=(const B2DPolygon& rPolygon)
    1125             :     {
    1126       84180 :         mpPolygon = rPolygon.mpPolygon;
    1127       84180 :         return *this;
    1128             :     }
    1129             : 
    1130          60 :     void B2DPolygon::makeUnique()
    1131             :     {
    1132          60 :         mpPolygon.make_unique();
    1133          60 :     }
    1134             : 
    1135       49997 :     bool B2DPolygon::operator==(const B2DPolygon& rPolygon) const
    1136             :     {
    1137       49997 :         if(mpPolygon.same_object(rPolygon.mpPolygon))
    1138        2110 :             return true;
    1139             : 
    1140       47887 :         return ((*mpPolygon) == (*rPolygon.mpPolygon));
    1141             :     }
    1142             : 
    1143        6857 :     bool B2DPolygon::operator!=(const B2DPolygon& rPolygon) const
    1144             :     {
    1145        6857 :         return !(*this == rPolygon);
    1146             :     }
    1147             : 
    1148    13975238 :     sal_uInt32 B2DPolygon::count() const
    1149             :     {
    1150    13975238 :         return mpPolygon->count();
    1151             :     }
    1152             : 
    1153   131483070 :     B2DPoint B2DPolygon::getB2DPoint(sal_uInt32 nIndex) const
    1154             :     {
    1155             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1156             : 
    1157   131483070 :         return mpPolygon->getPoint(nIndex);
    1158             :     }
    1159             : 
    1160    11962797 :     void B2DPolygon::setB2DPoint(sal_uInt32 nIndex, const B2DPoint& rValue)
    1161             :     {
    1162             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1163             : 
    1164    11962797 :         if(mpPolygon->getPoint(nIndex) != rValue)
    1165             :         {
    1166    11594941 :             mpPolygon->setPoint(nIndex, rValue);
    1167             :         }
    1168    11962797 :     }
    1169             : 
    1170       60314 :     void B2DPolygon::reserve(sal_uInt32 nCount)
    1171             :     {
    1172       60314 :         mpPolygon->reserve(nCount);
    1173       60314 :     }
    1174             : 
    1175         496 :     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         496 :         if(nCount)
    1180             :         {
    1181         496 :             mpPolygon->insert(nIndex, rPoint, nCount);
    1182             :         }
    1183         496 :     }
    1184             : 
    1185     3385038 :     void B2DPolygon::append(const B2DPoint& rPoint, sal_uInt32 nCount)
    1186             :     {
    1187     3385038 :         if(nCount)
    1188             :         {
    1189     3385038 :             mpPolygon->insert(mpPolygon->count(), rPoint, nCount);
    1190             :         }
    1191     3385038 :     }
    1192             : 
    1193    11566278 :     void B2DPolygon::append(const B2DPoint& rPoint)
    1194             :     {
    1195    11566278 :         mpPolygon->append(rPoint);
    1196    11566278 :     }
    1197             : 
    1198      757189 :     B2DPoint B2DPolygon::getPrevControlPoint(sal_uInt32 nIndex) const
    1199             :     {
    1200             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1201             : 
    1202      757189 :         if(mpPolygon->areControlPointsUsed())
    1203             :         {
    1204      709471 :             return mpPolygon->getPoint(nIndex) + mpPolygon->getPrevControlVector(nIndex);
    1205             :         }
    1206             :         else
    1207             :         {
    1208       47718 :             return mpPolygon->getPoint(nIndex);
    1209             :         }
    1210             :     }
    1211             : 
    1212      751472 :     B2DPoint B2DPolygon::getNextControlPoint(sal_uInt32 nIndex) const
    1213             :     {
    1214             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1215             : 
    1216      751472 :         if(mpPolygon->areControlPointsUsed())
    1217             :         {
    1218      703778 :             return mpPolygon->getPoint(nIndex) + mpPolygon->getNextControlVector(nIndex);
    1219             :         }
    1220             :         else
    1221             :         {
    1222       47694 :             return mpPolygon->getPoint(nIndex);
    1223             :         }
    1224             :     }
    1225             : 
    1226       17634 :     void B2DPolygon::setPrevControlPoint(sal_uInt32 nIndex, const B2DPoint& rValue)
    1227             :     {
    1228             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1229       17634 :         const basegfx::B2DVector aNewVector(rValue - mpPolygon->getPoint(nIndex));
    1230             : 
    1231       17634 :         if(mpPolygon->getPrevControlVector(nIndex) != aNewVector)
    1232             :         {
    1233       11857 :             mpPolygon->setPrevControlVector(nIndex, aNewVector);
    1234       17634 :         }
    1235       17634 :     }
    1236             : 
    1237       12989 :     void B2DPolygon::setNextControlPoint(sal_uInt32 nIndex, const B2DPoint& rValue)
    1238             :     {
    1239             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1240       12989 :         const basegfx::B2DVector aNewVector(rValue - mpPolygon->getPoint(nIndex));
    1241             : 
    1242       12989 :         if(mpPolygon->getNextControlVector(nIndex) != aNewVector)
    1243             :         {
    1244        7211 :             mpPolygon->setNextControlVector(nIndex, aNewVector);
    1245       12989 :         }
    1246       12989 :     }
    1247             : 
    1248           2 :     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           2 :         const B2DPoint aPoint(mpPolygon->getPoint(nIndex));
    1252           4 :         const basegfx::B2DVector aNewPrev(rPrev - aPoint);
    1253           4 :         const basegfx::B2DVector aNewNext(rNext - aPoint);
    1254             : 
    1255           2 :         if(mpPolygon->getPrevControlVector(nIndex) != aNewPrev || mpPolygon->getNextControlVector(nIndex) != aNewNext)
    1256             :         {
    1257           2 :             mpPolygon->setControlVectors(nIndex, aNewPrev, aNewNext);
    1258           2 :         }
    1259           2 :     }
    1260             : 
    1261          20 :     void B2DPolygon::resetPrevControlPoint(sal_uInt32 nIndex)
    1262             :     {
    1263             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1264             : 
    1265          20 :         if(mpPolygon->areControlPointsUsed() && !mpPolygon->getPrevControlVector(nIndex).equalZero())
    1266             :         {
    1267          20 :             mpPolygon->setPrevControlVector(nIndex, B2DVector::getEmptyVector());
    1268             :         }
    1269          20 :     }
    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           2 :     void B2DPolygon::resetControlPoints()
    1282             :     {
    1283           2 :         if(mpPolygon->areControlPointsUsed())
    1284             :         {
    1285           2 :             mpPolygon->resetControlVectors();
    1286             :         }
    1287           2 :     }
    1288             : 
    1289      125391 :     void B2DPolygon::appendBezierSegment(
    1290             :         const B2DPoint& rNextControlPoint,
    1291             :         const B2DPoint& rPrevControlPoint,
    1292             :         const B2DPoint& rPoint)
    1293             :     {
    1294      125391 :         const B2DVector aNewNextVector(mpPolygon->count() ? B2DVector(rNextControlPoint - mpPolygon->getPoint(mpPolygon->count() - 1)) : B2DVector::getEmptyVector());
    1295      250782 :         const B2DVector aNewPrevVector(rPrevControlPoint - rPoint);
    1296             : 
    1297      125391 :         if(aNewNextVector.equalZero() && aNewPrevVector.equalZero())
    1298             :         {
    1299        1509 :             mpPolygon->insert(mpPolygon->count(), rPoint, 1);
    1300             :         }
    1301             :         else
    1302             :         {
    1303      123882 :             mpPolygon->appendBezierSegment(aNewNextVector, aNewPrevVector, rPoint);
    1304      125391 :         }
    1305      125391 :     }
    1306             : 
    1307    12444506 :     bool B2DPolygon::areControlPointsUsed() const
    1308             :     {
    1309    12444506 :         return mpPolygon->areControlPointsUsed();
    1310             :     }
    1311             : 
    1312       23930 :     bool B2DPolygon::isPrevControlPointUsed(sal_uInt32 nIndex) const
    1313             :     {
    1314             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1315             : 
    1316       23930 :         return (mpPolygon->areControlPointsUsed() && !mpPolygon->getPrevControlVector(nIndex).equalZero());
    1317             :     }
    1318             : 
    1319       11296 :     bool B2DPolygon::isNextControlPointUsed(sal_uInt32 nIndex) const
    1320             :     {
    1321             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1322             : 
    1323       11296 :         return (mpPolygon->areControlPointsUsed() && !mpPolygon->getNextControlVector(nIndex).equalZero());
    1324             :     }
    1325             : 
    1326      140622 :     B2VectorContinuity B2DPolygon::getContinuityInPoint(sal_uInt32 nIndex) const
    1327             :     {
    1328             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1329             : 
    1330      140622 :         if(mpPolygon->areControlPointsUsed())
    1331             :         {
    1332      140622 :             const B2DVector& rPrev(mpPolygon->getPrevControlVector(nIndex));
    1333      140622 :             const B2DVector& rNext(mpPolygon->getNextControlVector(nIndex));
    1334             : 
    1335      140622 :             return getContinuity(rPrev, rNext);
    1336             :         }
    1337             :         else
    1338             :         {
    1339           0 :             return CONTINUITY_NONE;
    1340             :         }
    1341             :     }
    1342             : 
    1343      785173 :     void B2DPolygon::getBezierSegment(sal_uInt32 nIndex, B2DCubicBezier& rTarget) const
    1344             :     {
    1345             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
    1346      785173 :         const bool bNextIndexValidWithoutClose(nIndex + 1 < mpPolygon->count());
    1347             : 
    1348      785173 :         if(bNextIndexValidWithoutClose || mpPolygon->isClosed())
    1349             :         {
    1350      784803 :             const sal_uInt32 nNextIndex(bNextIndexValidWithoutClose ? nIndex + 1 : 0);
    1351      784803 :             rTarget.setStartPoint(mpPolygon->getPoint(nIndex));
    1352      784803 :             rTarget.setEndPoint(mpPolygon->getPoint(nNextIndex));
    1353             : 
    1354      784803 :             if(mpPolygon->areControlPointsUsed())
    1355             :             {
    1356      707104 :                 rTarget.setControlPointA(rTarget.getStartPoint() + mpPolygon->getNextControlVector(nIndex));
    1357      707104 :                 rTarget.setControlPointB(rTarget.getEndPoint() + mpPolygon->getPrevControlVector(nNextIndex));
    1358             :             }
    1359             :             else
    1360             :             {
    1361             :                 // no bezier, reset control poins at rTarget
    1362       77699 :                 rTarget.setControlPointA(rTarget.getStartPoint());
    1363       77699 :                 rTarget.setControlPointB(rTarget.getEndPoint());
    1364             :             }
    1365             :         }
    1366             :         else
    1367             :         {
    1368             :             // no valid edge at all, reset rTarget to current point
    1369         370 :             const B2DPoint aPoint(mpPolygon->getPoint(nIndex));
    1370         370 :             rTarget.setStartPoint(aPoint);
    1371         370 :             rTarget.setEndPoint(aPoint);
    1372         370 :             rTarget.setControlPointA(aPoint);
    1373         370 :             rTarget.setControlPointB(aPoint);
    1374             :         }
    1375      785173 :     }
    1376             : 
    1377        5471 :     B2DPolygon B2DPolygon::getDefaultAdaptiveSubdivision() const
    1378             :     {
    1379        5471 :         return mpPolygon->getDefaultAdaptiveSubdivision(*this);
    1380             :     }
    1381             : 
    1382     5579166 :     B2DRange B2DPolygon::getB2DRange() const
    1383             :     {
    1384     5579166 :         return mpPolygon->getB2DRange(*this);
    1385             :     }
    1386             : 
    1387        4966 :     void B2DPolygon::append(const B2DPolygon& rPoly, sal_uInt32 nIndex, sal_uInt32 nCount)
    1388             :     {
    1389        4966 :         if(rPoly.count())
    1390             :         {
    1391        4934 :             if(!nCount)
    1392             :             {
    1393        4934 :                 nCount = rPoly.count();
    1394             :             }
    1395             : 
    1396        4934 :             if(0 == nIndex && nCount == rPoly.count())
    1397             :             {
    1398        4934 :                 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        4966 :     }
    1408             : 
    1409       55860 :     void B2DPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount)
    1410             :     {
    1411             :         OSL_ENSURE(nIndex + nCount <= mpPolygon->count(), "B2DPolygon Remove outside range (!)");
    1412             : 
    1413       55860 :         if(nCount)
    1414             :         {
    1415       55860 :             mpPolygon->remove(nIndex, nCount);
    1416             :         }
    1417       55860 :     }
    1418             : 
    1419      147333 :     void B2DPolygon::clear()
    1420             :     {
    1421      147333 :         mpPolygon = DefaultPolygon::get();
    1422      147333 :     }
    1423             : 
    1424     6255591 :     bool B2DPolygon::isClosed() const
    1425             :     {
    1426     6255591 :         return mpPolygon->isClosed();
    1427             :     }
    1428             : 
    1429     5160261 :     void B2DPolygon::setClosed(bool bNew)
    1430             :     {
    1431     5160261 :         if(isClosed() != bNew)
    1432             :         {
    1433     4916775 :             mpPolygon->setClosed(bNew);
    1434             :         }
    1435     5160261 :     }
    1436             : 
    1437         765 :     void B2DPolygon::flip()
    1438             :     {
    1439         765 :         if(count() > 1)
    1440             :         {
    1441         765 :             mpPolygon->flip();
    1442             :         }
    1443         765 :     }
    1444             : 
    1445       32973 :     bool B2DPolygon::hasDoublePoints() const
    1446             :     {
    1447       32973 :         return (mpPolygon->count() > 1 && mpPolygon->hasDoublePoints());
    1448             :     }
    1449             : 
    1450       28122 :     void B2DPolygon::removeDoublePoints()
    1451             :     {
    1452       28122 :         if(hasDoublePoints())
    1453             :         {
    1454        4683 :             mpPolygon->removeDoublePointsAtBeginEnd();
    1455        4683 :             mpPolygon->removeDoublePointsWholeTrack();
    1456             :         }
    1457       28122 :     }
    1458             : 
    1459      899752 :     void B2DPolygon::transform(const B2DHomMatrix& rMatrix)
    1460             :     {
    1461      899752 :         if(mpPolygon->count() && !rMatrix.isIdentity())
    1462             :         {
    1463      872081 :             mpPolygon->transform(rMatrix);
    1464             :         }
    1465      899752 :     }
    1466             : 
    1467             : } // end of namespace basegfx
    1468             : 
    1469             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10