LCOV - code coverage report
Current view: top level - basegfx/source/polygon - b2dpolygoncutandtouch.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 348 436 79.8 %
Date: 2012-08-25 Functions: 26 30 86.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 398 800 49.8 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : #include <basegfx/polygon/b2dpolygoncutandtouch.hxx>
      30                 :            : #include <osl/diagnose.h>
      31                 :            : #include <basegfx/numeric/ftools.hxx>
      32                 :            : #include <basegfx/point/b2dpoint.hxx>
      33                 :            : #include <basegfx/vector/b2dvector.hxx>
      34                 :            : #include <basegfx/range/b2drange.hxx>
      35                 :            : #include <basegfx/polygon/b2dpolygontools.hxx>
      36                 :            : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      37                 :            : #include <basegfx/curve/b2dcubicbezier.hxx>
      38                 :            : 
      39                 :            : #include <vector>
      40                 :            : #include <algorithm>
      41                 :            : 
      42                 :            : 
      43                 :            : #define SUBDIVIDE_FOR_CUT_TEST_COUNT        (50)
      44                 :            : 
      45                 :            : //////////////////////////////////////////////////////////////////////////////
      46                 :            : 
      47                 :            : namespace basegfx
      48                 :            : {
      49                 :            :     namespace
      50                 :            :     {
      51                 :            :         ////////////////////////////////////////////////////////////////////////////////
      52                 :            : 
      53                 :      33825 :         class temporaryPoint
      54                 :            :         {
      55                 :            :             B2DPoint                            maPoint;        // the new point
      56                 :            :             sal_uInt32                          mnIndex;        // index after which to insert
      57                 :            :             double                              mfCut;          // parametric cut description [0.0 .. 1.0]
      58                 :            : 
      59                 :            :         public:
      60                 :       4850 :             temporaryPoint(const B2DPoint& rNewPoint, sal_uInt32 nIndex, double fCut)
      61                 :            :             :   maPoint(rNewPoint),
      62                 :            :                 mnIndex(nIndex),
      63                 :       4850 :                 mfCut(fCut)
      64                 :            :             {
      65                 :       4850 :             }
      66                 :            : 
      67                 :       6663 :             bool operator<(const temporaryPoint& rComp) const
      68                 :            :             {
      69         [ +  + ]:       6663 :                 if(mnIndex == rComp.mnIndex)
      70                 :            :                 {
      71                 :       1529 :                     return (mfCut < rComp.mfCut);
      72                 :            :                 }
      73                 :            : 
      74                 :       6663 :                 return (mnIndex < rComp.mnIndex);
      75                 :            :             }
      76                 :            : 
      77                 :       4758 :             const B2DPoint& getPoint() const { return maPoint; }
      78                 :       9584 :             sal_uInt32 getIndex() const { return mnIndex; }
      79                 :          0 :             double getCut() const { return mfCut; }
      80                 :            :         };
      81                 :            : 
      82                 :            :         ////////////////////////////////////////////////////////////////////////////////
      83                 :            : 
      84                 :            :         typedef ::std::vector< temporaryPoint > temporaryPointVector;
      85                 :            : 
      86                 :            :         ////////////////////////////////////////////////////////////////////////////////
      87                 :            : 
      88 [ +  - ][ +  - ]:       4550 :         class temporaryPolygonData
      89                 :            :         {
      90                 :            :             B2DPolygon                              maPolygon;
      91                 :            :             B2DRange                                maRange;
      92                 :            :             temporaryPointVector                    maPoints;
      93                 :            : 
      94                 :            :         public:
      95                 :       8983 :             const B2DPolygon& getPolygon() const { return maPolygon; }
      96                 :       2275 :             void setPolygon(const B2DPolygon& rNew) { maPolygon = rNew; maRange = tools::getRange(maPolygon); }
      97                 :       7638 :             const B2DRange& getRange() const { return maRange; }
      98                 :       6747 :             temporaryPointVector& getTemporaryPointVector() { return maPoints; }
      99                 :            :         };
     100                 :            : 
     101                 :            :         ////////////////////////////////////////////////////////////////////////////////
     102                 :            : 
     103                 :       5410 :         B2DPolygon mergeTemporaryPointsAndPolygon(const B2DPolygon& rCandidate, temporaryPointVector& rTempPoints)
     104                 :            :         {
     105                 :            :             // #i76891# mergeTemporaryPointsAndPolygon redesigned to be able to correctly handle
     106                 :            :             // single edges with/without control points
     107                 :            :             // #i101491# added counter for non-changing element count
     108                 :       5410 :             const sal_uInt32 nTempPointCount(rTempPoints.size());
     109                 :            : 
     110         [ +  + ]:       5410 :             if(nTempPointCount)
     111                 :            :             {
     112         [ +  - ]:       1334 :                 B2DPolygon aRetval;
     113         [ +  - ]:       1334 :                 const sal_uInt32 nCount(rCandidate.count());
     114                 :            : 
     115         [ +  - ]:       1334 :                 if(nCount)
     116                 :            :                 {
     117                 :            :                     // sort temp points to assure increasing fCut values and increasing indices
     118         [ +  - ]:       1334 :                     ::std::sort(rTempPoints.begin(), rTempPoints.end());
     119                 :            : 
     120                 :            :                     // prepare loop
     121         [ +  - ]:       1334 :                     B2DCubicBezier aEdge;
     122                 :       1334 :                     sal_uInt32 nNewInd(0L);
     123                 :            : 
     124                 :            :                     // add start point
     125 [ +  - ][ +  - ]:       1334 :                     aRetval.append(rCandidate.getB2DPoint(0));
     126                 :            : 
     127         [ +  + ]:       7856 :                     for(sal_uInt32 a(0L); a < nCount; a++)
     128                 :            :                     {
     129                 :            :                         // get edge
     130         [ +  - ]:       6522 :                         rCandidate.getBezierSegment(a, aEdge);
     131                 :            : 
     132 [ +  - ][ -  + ]:       6522 :                         if(aEdge.isBezier())
     133                 :            :                         {
     134                 :            :                             // control vectors involved for this edge
     135                 :          0 :                             double fLeftStart(0.0);
     136                 :            : 
     137                 :            :                             // now add all points targeted to be at this index
     138 [ #  # ][ #  # ]:          0 :                             while(nNewInd < nTempPointCount && rTempPoints[nNewInd].getIndex() == a)
                 [ #  # ]
     139                 :            :                             {
     140                 :          0 :                                 const temporaryPoint& rTempPoint = rTempPoints[nNewInd++];
     141                 :            : 
     142                 :            :                                 // split curve segment. Splits need to come sorted and need to be < 1.0. Also,
     143                 :            :                                 // since original segment is consumed from left to right, the cut values need
     144                 :            :                                 // to be scaled to the remaining part
     145         [ #  # ]:          0 :                                 B2DCubicBezier aLeftPart;
     146                 :          0 :                                 const double fRelativeSplitPoint((rTempPoint.getCut() - fLeftStart) / (1.0 - fLeftStart));
     147         [ #  # ]:          0 :                                 aEdge.split(fRelativeSplitPoint, &aLeftPart, &aEdge);
     148                 :          0 :                                 fLeftStart = rTempPoint.getCut();
     149                 :            : 
     150                 :            :                                 // add left bow
     151         [ #  # ]:          0 :                                 aRetval.appendBezierSegment(aLeftPart.getControlPointA(), aLeftPart.getControlPointB(), rTempPoint.getPoint());
     152         [ #  # ]:          0 :                             }
     153                 :            : 
     154                 :            :                             // add remaining bow
     155         [ #  # ]:          0 :                             aRetval.appendBezierSegment(aEdge.getControlPointA(), aEdge.getControlPointB(), aEdge.getEndPoint());
     156                 :            :                         }
     157                 :            :                         else
     158                 :            :                         {
     159                 :            :                             // add all points targeted to be at this index
     160 [ +  + ][ +  + ]:      11280 :                             while(nNewInd < nTempPointCount && rTempPoints[nNewInd].getIndex() == a)
                 [ +  + ]
     161                 :            :                             {
     162                 :       4758 :                                 const temporaryPoint& rTempPoint = rTempPoints[nNewInd++];
     163                 :       4758 :                                 const B2DPoint aNewPoint(rTempPoint.getPoint());
     164                 :            : 
     165                 :            :                                 // do not add points double
     166 [ +  - ][ +  + ]:       4758 :                                 if(!aRetval.getB2DPoint(aRetval.count() - 1L).equal(aNewPoint))
                 [ +  - ]
     167                 :            :                                 {
     168         [ +  - ]:       4743 :                                     aRetval.append(aNewPoint);
     169                 :            :                                 }
     170                 :       4758 :                             }
     171                 :            : 
     172                 :            :                             // add edge end point
     173         [ +  - ]:       6522 :                             aRetval.append(aEdge.getEndPoint());
     174                 :            :                         }
     175         [ +  - ]:       1334 :                     }
     176                 :            :                 }
     177                 :            : 
     178 [ +  - ][ +  + ]:       1334 :                 if(rCandidate.isClosed())
     179                 :            :                 {
     180                 :            :                     // set closed flag and correct last point (which is added double now).
     181         [ +  - ]:       1288 :                     tools::closeWithGeometryChange(aRetval);
     182                 :            :                 }
     183                 :            : 
     184 [ +  - ][ +  - ]:       1334 :                 return aRetval;
     185                 :            :             }
     186                 :            :             else
     187                 :            :             {
     188                 :       5410 :                 return rCandidate;
     189                 :            :             }
     190                 :            :         }
     191                 :            : 
     192                 :            :         ////////////////////////////////////////////////////////////////////////////////
     193                 :            : 
     194                 :          0 :         void adaptAndTransferCutsWithBezierSegment(
     195                 :            :             const temporaryPointVector& rPointVector, const B2DPolygon& rPolygon,
     196                 :            :             sal_uInt32 nInd, temporaryPointVector& rTempPoints)
     197                 :            :         {
     198                 :            :             // assuming that the subdivision to create rPolygon used aequidistant pieces
     199                 :            :             // (as in adaptiveSubdivideByCount) it is now possible to calculate back the
     200                 :            :             // cut positions in the polygon to relative cut positions on the original bezier
     201                 :            :             // segment.
     202                 :          0 :             const sal_uInt32 nTempPointCount(rPointVector.size());
     203         [ #  # ]:          0 :             const sal_uInt32 nEdgeCount(rPolygon.count() ? rPolygon.count() - 1L : 0L);
     204                 :            : 
     205 [ #  # ][ #  # ]:          0 :             if(nTempPointCount && nEdgeCount)
     206                 :            :             {
     207         [ #  # ]:          0 :                 for(sal_uInt32 a(0L); a < nTempPointCount; a++)
     208                 :            :                 {
     209                 :          0 :                     const temporaryPoint& rTempPoint = rPointVector[a];
     210                 :          0 :                     const double fCutPosInPolygon((double)rTempPoint.getIndex() + rTempPoint.getCut());
     211                 :          0 :                     const double fRelativeCutPos(fCutPosInPolygon / (double)nEdgeCount);
     212         [ #  # ]:          0 :                     rTempPoints.push_back(temporaryPoint(rTempPoint.getPoint(), nInd, fRelativeCutPos));
     213                 :            :                 }
     214                 :            :             }
     215                 :          0 :         }
     216                 :            : 
     217                 :            :         ////////////////////////////////////////////////////////////////////////////////
     218                 :            : 
     219                 :            :     } // end of anonymous namespace
     220                 :            : } // end of namespace basegfx
     221                 :            : 
     222                 :            : //////////////////////////////////////////////////////////////////////////////
     223                 :            : 
     224                 :            : namespace basegfx
     225                 :            : {
     226                 :            :     namespace
     227                 :            :     {
     228                 :            :         ////////////////////////////////////////////////////////////////////////////////
     229                 :            :         // predefines for calls to this methods before method implementation
     230                 :            : 
     231                 :            :         void findCuts(const B2DPolygon& rCandidate, temporaryPointVector& rTempPoints);
     232                 :            :         void findTouches(const B2DPolygon& rEdgePolygon, const B2DPolygon& rPointPolygon, temporaryPointVector& rTempPoints);
     233                 :            :         void findCuts(const B2DPolygon& rCandidateA, const B2DPolygon& rCandidateB, temporaryPointVector& rTempPointsA, temporaryPointVector& rTempPointsB);
     234                 :            : 
     235                 :            :         ////////////////////////////////////////////////////////////////////////////////
     236                 :            : 
     237                 :       6739 :         void findEdgeCutsTwoEdges(
     238                 :            :             const B2DPoint& rCurrA, const B2DPoint& rNextA,
     239                 :            :             const B2DPoint& rCurrB, const B2DPoint& rNextB,
     240                 :            :             sal_uInt32 nIndA, sal_uInt32 nIndB,
     241                 :            :             temporaryPointVector& rTempPointsA, temporaryPointVector& rTempPointsB)
     242                 :            :         {
     243                 :            :             // no null length edges
     244 [ +  + ][ +  + ]:       6739 :             if(!(rCurrA.equal(rNextA) || rCurrB.equal(rNextB)))
                 [ +  + ]
     245                 :            :             {
     246                 :            :                 // no common start/end points, this can be no cuts
     247 [ +  + ][ +  + ]:       6677 :                 if(!(rCurrB.equal(rCurrA) || rCurrB.equal(rNextA) || rNextB.equal(rCurrA) || rNextB.equal(rNextA)))
         [ +  + ][ +  + ]
                 [ +  + ]
     248                 :            :                 {
     249                 :       4014 :                     const B2DVector aVecA(rNextA - rCurrA);
     250                 :       4014 :                     const B2DVector aVecB(rNextB - rCurrB);
     251         [ +  - ]:       4014 :                     double fCut(aVecA.cross(aVecB));
     252                 :            : 
     253         [ +  + ]:       4014 :                     if(!fTools::equalZero(fCut))
     254                 :            :                     {
     255                 :       3979 :                         const double fZero(0.0);
     256                 :       3979 :                         const double fOne(1.0);
     257                 :       3979 :                         fCut = (aVecB.getY() * (rCurrB.getX() - rCurrA.getX()) + aVecB.getX() * (rCurrA.getY() - rCurrB.getY())) / fCut;
     258                 :            : 
     259 [ +  + ][ +  + ]:       3979 :                         if(fTools::more(fCut, fZero) && fTools::less(fCut, fOne))
                 [ +  + ]
     260                 :            :                         {
     261                 :            :                             // it's a candidate, but also need to test parameter value of cut on line 2
     262                 :            :                             double fCut2;
     263                 :            : 
     264                 :            :                             // choose the more precise version
     265         [ +  + ]:       2409 :                             if(fabs(aVecB.getX()) > fabs(aVecB.getY()))
     266                 :            :                             {
     267                 :       1391 :                                 fCut2 = (rCurrA.getX() + (fCut * aVecA.getX()) - rCurrB.getX()) / aVecB.getX();
     268                 :            :                             }
     269                 :            :                             else
     270                 :            :                             {
     271                 :       1018 :                                 fCut2 = (rCurrA.getY() + (fCut * aVecA.getY()) - rCurrB.getY()) / aVecB.getY();
     272                 :            :                             }
     273                 :            : 
     274 [ +  + ][ +  + ]:       2409 :                             if(fTools::more(fCut2, fZero) && fTools::less(fCut2, fOne))
                 [ +  + ]
     275                 :            :                             {
     276                 :            :                                 // cut is in range, add point. Two edges can have only one cut, but
     277                 :            :                                 // add a cut point to each list. The lists may be the same for
     278                 :            :                                 // self intersections.
     279                 :       2223 :                                 const B2DPoint aCutPoint(interpolate(rCurrA, rNextA, fCut));
     280         [ +  - ]:       2223 :                                 rTempPointsA.push_back(temporaryPoint(aCutPoint, nIndA, fCut));
     281         [ +  - ]:       3979 :                                 rTempPointsB.push_back(temporaryPoint(aCutPoint, nIndB, fCut2));
     282                 :            :                             }
     283                 :            :                         }
     284                 :       4014 :                     }
     285                 :            :                 }
     286                 :            :             }
     287                 :       6739 :         }
     288                 :            : 
     289                 :            :         ////////////////////////////////////////////////////////////////////////////////
     290                 :            : 
     291                 :          5 :         void findCutsAndTouchesAndCommonForBezier(const B2DPolygon& rCandidateA, const B2DPolygon& rCandidateB, temporaryPointVector& rTempPointsA, temporaryPointVector& rTempPointsB)
     292                 :            :         {
     293                 :            :             // #i76891#
     294                 :            :             // This new method is necessary since in findEdgeCutsBezierAndEdge and in findEdgeCutsTwoBeziers
     295                 :            :             // it is not sufficient to use findCuts() recursively. This will indeed find the cuts between the
     296                 :            :             // segments of the two temporarily adaptive subdivided bezier segments, but not the touches or
     297                 :            :             // equal points of them.
     298                 :            :             // It would be possible to find the toches using findTouches(), but at last with commpn points
     299                 :            :             // the adding of cut points (temporary points) would fail. But for these temporarily adaptive
     300                 :            :             // subdivided bezier segments, common points may be not very likely, but the bug shows that it
     301                 :            :             // happens.
     302                 :            :             // Touch points are a little bit more likely than common points. All in all it is best to use
     303                 :            :             // a specialized method here which can profit from knowing that it is working on a special
     304                 :            :             // family of B2DPolygons: no curve segments included and not closed.
     305                 :            :             OSL_ENSURE(!rCandidateA.areControlPointsUsed() && !rCandidateB.areControlPointsUsed(), "findCutsAndTouchesAndCommonForBezier only works with subdivided polygons (!)");
     306                 :            :             OSL_ENSURE(!rCandidateA.isClosed() && !rCandidateB.isClosed(), "findCutsAndTouchesAndCommonForBezier only works with opened polygons (!)");
     307                 :          5 :             const sal_uInt32 nPointCountA(rCandidateA.count());
     308                 :          5 :             const sal_uInt32 nPointCountB(rCandidateB.count());
     309                 :            : 
     310 [ +  - ][ +  - ]:          5 :             if(nPointCountA > 1 && nPointCountB > 1)
     311                 :            :             {
     312                 :          5 :                 const sal_uInt32 nEdgeCountA(nPointCountA - 1);
     313                 :          5 :                 const sal_uInt32 nEdgeCountB(nPointCountB - 1);
     314         [ +  - ]:          5 :                 B2DPoint aCurrA(rCandidateA.getB2DPoint(0L));
     315                 :            : 
     316         [ +  + ]:        260 :                 for(sal_uInt32 a(0L); a < nEdgeCountA; a++)
     317                 :            :                 {
     318         [ +  - ]:        255 :                     const B2DPoint aNextA(rCandidateA.getB2DPoint(a + 1L));
     319         [ +  - ]:        255 :                     const B2DRange aRangeA(aCurrA, aNextA);
     320         [ +  - ]:        255 :                     B2DPoint aCurrB(rCandidateB.getB2DPoint(0L));
     321                 :            : 
     322         [ +  + ]:      13260 :                     for(sal_uInt32 b(0L); b < nEdgeCountB; b++)
     323                 :            :                     {
     324         [ +  - ]:      13005 :                         const B2DPoint aNextB(rCandidateB.getB2DPoint(b + 1L));
     325         [ +  - ]:      13005 :                         const B2DRange aRangeB(aCurrB, aNextB);
     326                 :            : 
     327 [ +  - ][ +  + ]:      13005 :                         if(aRangeA.overlaps(aRangeB))
     328                 :            :                         {
     329                 :            :                             // no null length edges
     330 [ +  - ][ +  - ]:        755 :                             if(!(aCurrA.equal(aNextA) || aCurrB.equal(aNextB)))
                 [ +  - ]
     331                 :            :                             {
     332                 :        755 :                                 const B2DVector aVecA(aNextA - aCurrA);
     333                 :        755 :                                 const B2DVector aVecB(aNextB - aCurrB);
     334         [ +  - ]:        755 :                                 double fCutA(aVecA.cross(aVecB));
     335                 :            : 
     336         [ +  + ]:        755 :                                 if(!fTools::equalZero(fCutA))
     337                 :            :                                 {
     338                 :        500 :                                     const double fZero(0.0);
     339                 :        500 :                                     const double fOne(1.0);
     340                 :        500 :                                     fCutA = (aVecB.getY() * (aCurrB.getX() - aCurrA.getX()) + aVecB.getX() * (aCurrA.getY() - aCurrB.getY())) / fCutA;
     341                 :            : 
     342                 :            :                                     // use range [0.0 .. 1.0[, thus in the loop, all direct aCurrA cuts will be registered
     343                 :            :                                     // as 0.0 cut. The 1.0 cut will be registered in the next loop step
     344 [ +  + ][ +  + ]:        500 :                                     if(fTools::moreOrEqual(fCutA, fZero) && fTools::less(fCutA, fOne))
                 [ +  + ]
     345                 :            :                                     {
     346                 :            :                                         // it's a candidate, but also need to test parameter value of cut on line 2
     347                 :            :                                         double fCutB;
     348                 :            : 
     349                 :            :                                         // choose the more precise version
     350         [ +  + ]:        135 :                                         if(fabs(aVecB.getX()) > fabs(aVecB.getY()))
     351                 :            :                                         {
     352                 :         55 :                                             fCutB = (aCurrA.getX() + (fCutA * aVecA.getX()) - aCurrB.getX()) / aVecB.getX();
     353                 :            :                                         }
     354                 :            :                                         else
     355                 :            :                                         {
     356                 :         80 :                                             fCutB = (aCurrA.getY() + (fCutA * aVecA.getY()) - aCurrB.getY()) / aVecB.getY();
     357                 :            :                                         }
     358                 :            : 
     359                 :            :                                         // use range [0.0 .. 1.0[, thus in the loop, all direct aCurrA cuts will be registered
     360                 :            :                                         // as 0.0 cut. The 1.0 cut will be registered in the next loop step
     361 [ +  - ][ -  + ]:        135 :                                         if(fTools::moreOrEqual(fCutB, fZero) && fTools::less(fCutB, fOne))
                 [ -  + ]
     362                 :            :                                         {
     363                 :            :                                             // cut is in both ranges. Add points for A and B
     364                 :            :                                             // #i111715# use fTools::equal instead of fTools::equalZero for better accuracy
     365         [ #  # ]:          0 :                                             if(fTools::equal(fCutA, fZero))
     366                 :            :                                             {
     367                 :            :                                                 // ignore for start point in first edge; this is handled
     368                 :            :                                                 // by outer methods and would just produce a double point
     369         [ #  # ]:          0 :                                                 if(a)
     370                 :            :                                                 {
     371         [ #  # ]:          0 :                                                     rTempPointsA.push_back(temporaryPoint(aCurrA, a, 0.0));
     372                 :            :                                                 }
     373                 :            :                                             }
     374                 :            :                                             else
     375                 :            :                                             {
     376                 :          0 :                                                 const B2DPoint aCutPoint(interpolate(aCurrA, aNextA, fCutA));
     377         [ #  # ]:          0 :                                                 rTempPointsA.push_back(temporaryPoint(aCutPoint, a, fCutA));
     378                 :            :                                             }
     379                 :            : 
     380                 :            :                                             // #i111715# use fTools::equal instead of fTools::equalZero for better accuracy
     381         [ #  # ]:          0 :                                             if(fTools::equal(fCutB, fZero))
     382                 :            :                                             {
     383                 :            :                                                 // ignore for start point in first edge; this is handled
     384                 :            :                                                 // by outer methods and would just produce a double point
     385         [ #  # ]:          0 :                                                 if(b)
     386                 :            :                                                 {
     387         [ #  # ]:          0 :                                                     rTempPointsB.push_back(temporaryPoint(aCurrB, b, 0.0));
     388                 :            :                                                 }
     389                 :            :                                             }
     390                 :            :                                             else
     391                 :            :                                             {
     392                 :          0 :                                                 const B2DPoint aCutPoint(interpolate(aCurrB, aNextB, fCutB));
     393         [ #  # ]:        500 :                                                 rTempPointsB.push_back(temporaryPoint(aCutPoint, b, fCutB));
     394                 :            :                                             }
     395                 :            :                                         }
     396                 :            :                                     }
     397                 :        755 :                                 }
     398                 :            :                             }
     399                 :            :                         }
     400                 :            : 
     401                 :            :                         // prepare next step
     402                 :      13005 :                         aCurrB = aNextB;
     403                 :      13005 :                     }
     404                 :            : 
     405                 :            :                     // prepare next step
     406                 :        255 :                     aCurrA = aNextA;
     407                 :        260 :                 }
     408                 :            :             }
     409                 :          5 :         }
     410                 :            : 
     411                 :            :         ////////////////////////////////////////////////////////////////////////////////
     412                 :            : 
     413                 :          0 :         void findEdgeCutsBezierAndEdge(
     414                 :            :             const B2DCubicBezier& rCubicA,
     415                 :            :             const B2DPoint& rCurrB, const B2DPoint& rNextB,
     416                 :            :             sal_uInt32 nIndA, sal_uInt32 nIndB,
     417                 :            :             temporaryPointVector& rTempPointsA, temporaryPointVector& rTempPointsB)
     418                 :            :         {
     419                 :            :             // find all cuts between given bezier segment and edge. Add an entry to the tempPoints
     420                 :            :             // for each common point with the cut value describing the relative position on given
     421                 :            :             // bezier segment and edge.
     422         [ #  # ]:          0 :             B2DPolygon aTempPolygonA;
     423         [ #  # ]:          0 :             B2DPolygon aTempPolygonEdge;
     424         [ #  # ]:          0 :             temporaryPointVector aTempPointVectorA;
     425         [ #  # ]:          0 :             temporaryPointVector aTempPointVectorEdge;
     426                 :            : 
     427                 :            :             // create subdivided polygons and find cuts between them
     428                 :            :             // Keep adaptiveSubdivideByCount due to needed quality
     429         [ #  # ]:          0 :             aTempPolygonA.reserve(SUBDIVIDE_FOR_CUT_TEST_COUNT + 8);
     430         [ #  # ]:          0 :             aTempPolygonA.append(rCubicA.getStartPoint());
     431         [ #  # ]:          0 :             rCubicA.adaptiveSubdivideByCount(aTempPolygonA, SUBDIVIDE_FOR_CUT_TEST_COUNT);
     432         [ #  # ]:          0 :             aTempPolygonEdge.append(rCurrB);
     433         [ #  # ]:          0 :             aTempPolygonEdge.append(rNextB);
     434                 :            : 
     435                 :            :             // #i76891# using findCuts recursively is not sufficient here
     436         [ #  # ]:          0 :             findCutsAndTouchesAndCommonForBezier(aTempPolygonA, aTempPolygonEdge, aTempPointVectorA, aTempPointVectorEdge);
     437                 :            : 
     438         [ #  # ]:          0 :             if(!aTempPointVectorA.empty())
     439                 :            :             {
     440                 :            :                 // adapt tempVector entries to segment
     441         [ #  # ]:          0 :                 adaptAndTransferCutsWithBezierSegment(aTempPointVectorA, aTempPolygonA, nIndA, rTempPointsA);
     442                 :            :             }
     443                 :            : 
     444                 :            :             // append remapped tempVector entries for edge to tempPoints for edge
     445         [ #  # ]:          0 :             for(sal_uInt32 a(0L); a < aTempPointVectorEdge.size(); a++)
     446                 :            :             {
     447                 :          0 :                 const temporaryPoint& rTempPoint = aTempPointVectorEdge[a];
     448         [ #  # ]:          0 :                 rTempPointsB.push_back(temporaryPoint(rTempPoint.getPoint(), nIndB, rTempPoint.getCut()));
     449 [ #  # ][ #  # ]:          0 :             }
     450                 :          0 :         }
     451                 :            : 
     452                 :            :         ////////////////////////////////////////////////////////////////////////////////
     453                 :            : 
     454                 :          5 :         void findEdgeCutsTwoBeziers(
     455                 :            :             const B2DCubicBezier& rCubicA,
     456                 :            :             const B2DCubicBezier& rCubicB,
     457                 :            :             sal_uInt32 nIndA, sal_uInt32 nIndB,
     458                 :            :             temporaryPointVector& rTempPointsA, temporaryPointVector& rTempPointsB)
     459                 :            :         {
     460                 :            :             // find all cuts between the two given bezier segments. Add an entry to the tempPoints
     461                 :            :             // for each common point with the cut value describing the relative position on given
     462                 :            :             // bezier segments.
     463         [ +  - ]:          5 :             B2DPolygon aTempPolygonA;
     464         [ +  - ]:          5 :             B2DPolygon aTempPolygonB;
     465         [ +  - ]:          5 :             temporaryPointVector aTempPointVectorA;
     466         [ +  - ]:          5 :             temporaryPointVector aTempPointVectorB;
     467                 :            : 
     468                 :            :             // create subdivided polygons and find cuts between them
     469                 :            :             // Keep adaptiveSubdivideByCount due to needed quality
     470         [ +  - ]:          5 :             aTempPolygonA.reserve(SUBDIVIDE_FOR_CUT_TEST_COUNT + 8);
     471         [ +  - ]:          5 :             aTempPolygonA.append(rCubicA.getStartPoint());
     472         [ +  - ]:          5 :             rCubicA.adaptiveSubdivideByCount(aTempPolygonA, SUBDIVIDE_FOR_CUT_TEST_COUNT);
     473         [ +  - ]:          5 :             aTempPolygonB.reserve(SUBDIVIDE_FOR_CUT_TEST_COUNT + 8);
     474         [ +  - ]:          5 :             aTempPolygonB.append(rCubicB.getStartPoint());
     475         [ +  - ]:          5 :             rCubicB.adaptiveSubdivideByCount(aTempPolygonB, SUBDIVIDE_FOR_CUT_TEST_COUNT);
     476                 :            : 
     477                 :            :             // #i76891# using findCuts recursively is not sufficient here
     478         [ +  - ]:          5 :             findCutsAndTouchesAndCommonForBezier(aTempPolygonA, aTempPolygonB, aTempPointVectorA, aTempPointVectorB);
     479                 :            : 
     480         [ -  + ]:          5 :             if(!aTempPointVectorA.empty())
     481                 :            :             {
     482                 :            :                 // adapt tempVector entries to segment
     483         [ #  # ]:          0 :                 adaptAndTransferCutsWithBezierSegment(aTempPointVectorA, aTempPolygonA, nIndA, rTempPointsA);
     484                 :            :             }
     485                 :            : 
     486         [ -  + ]:          5 :             if(!aTempPointVectorB.empty())
     487                 :            :             {
     488                 :            :                 // adapt tempVector entries to segment
     489         [ #  # ]:          0 :                 adaptAndTransferCutsWithBezierSegment(aTempPointVectorB, aTempPolygonB, nIndB, rTempPointsB);
     490 [ +  - ][ +  - ]:          5 :             }
     491                 :          5 :         }
     492                 :            : 
     493                 :            :         ////////////////////////////////////////////////////////////////////////////////
     494                 :            : 
     495                 :         10 :         void findEdgeCutsOneBezier(
     496                 :            :             const B2DCubicBezier& rCubicA,
     497                 :            :             sal_uInt32 nInd, temporaryPointVector& rTempPoints)
     498                 :            :         {
     499                 :            :             // avoid expensive part of this method if possible
     500                 :            :             // TODO: use hasAnyExtremum() method instead when it becomes available
     501                 :            :             double fDummy;
     502         [ +  - ]:         10 :             const bool bHasAnyExtremum = rCubicA.getMinimumExtremumPosition( fDummy );
     503         [ +  - ]:         10 :             if( !bHasAnyExtremum )
     504                 :         10 :                 return;
     505                 :            : 
     506                 :            :             // find all self-intersections on the given bezier segment. Add an entry to the tempPoints
     507                 :            :             // for each self intersection point with the cut value describing the relative position on given
     508                 :            :             // bezier segment.
     509         [ +  - ]:         10 :             B2DPolygon aTempPolygon;
     510         [ +  - ]:         10 :             temporaryPointVector aTempPointVector;
     511                 :            : 
     512                 :            :             // create subdivided polygon and find cuts on it
     513                 :            :             // Keep adaptiveSubdivideByCount due to needed quality
     514         [ +  - ]:         10 :             aTempPolygon.reserve(SUBDIVIDE_FOR_CUT_TEST_COUNT + 8);
     515         [ +  - ]:         10 :             aTempPolygon.append(rCubicA.getStartPoint());
     516         [ +  - ]:         10 :             rCubicA.adaptiveSubdivideByCount(aTempPolygon, SUBDIVIDE_FOR_CUT_TEST_COUNT);
     517         [ +  - ]:         10 :             findCuts(aTempPolygon, aTempPointVector);
     518                 :            : 
     519         [ -  + ]:         10 :             if(!aTempPointVector.empty())
     520                 :            :             {
     521                 :            :                 // adapt tempVector entries to segment
     522         [ #  # ]:          0 :                 adaptAndTransferCutsWithBezierSegment(aTempPointVector, aTempPolygon, nInd, rTempPoints);
     523         [ +  - ]:         10 :             }
     524                 :            :         }
     525                 :            : 
     526                 :            :         ////////////////////////////////////////////////////////////////////////////////
     527                 :            : 
     528                 :       2343 :         void findCuts(const B2DPolygon& rCandidate, temporaryPointVector& rTempPoints)
     529                 :            :         {
     530                 :            :             // find out if there are edges with intersections (self-cuts). If yes, add
     531                 :            :             // entries to rTempPoints accordingly
     532                 :       2343 :             const sal_uInt32 nPointCount(rCandidate.count());
     533                 :            : 
     534         [ +  - ]:       2343 :             if(nPointCount)
     535                 :            :             {
     536         [ +  + ]:       2343 :                 const sal_uInt32 nEdgeCount(rCandidate.isClosed() ? nPointCount : nPointCount - 1L);
     537                 :            : 
     538         [ +  - ]:       2343 :                 if(nEdgeCount)
     539                 :            :                 {
     540                 :       2343 :                     const bool bCurvesInvolved(rCandidate.areControlPointsUsed());
     541                 :            : 
     542         [ +  + ]:       2343 :                     if(bCurvesInvolved)
     543                 :            :                     {
     544         [ +  - ]:         10 :                         B2DCubicBezier aCubicA;
     545         [ +  - ]:         10 :                         B2DCubicBezier aCubicB;
     546                 :            : 
     547         [ +  + ]:         70 :                         for(sal_uInt32 a(0L); a < nEdgeCount - 1L; a++)
     548                 :            :                         {
     549         [ +  - ]:         60 :                             rCandidate.getBezierSegment(a, aCubicA);
     550         [ +  - ]:         60 :                             aCubicA.testAndSolveTrivialBezier();
     551         [ +  - ]:         60 :                             const bool bEdgeAIsCurve(aCubicA.isBezier());
     552         [ +  - ]:         60 :                             const B2DRange aRangeA(aCubicA.getRange());
     553                 :            : 
     554         [ +  + ]:         60 :                             if(bEdgeAIsCurve)
     555                 :            :                             {
     556                 :            :                                 // curved segments may have self-intersections, do not forget those (!)
     557         [ +  - ]:         10 :                                 findEdgeCutsOneBezier(aCubicA, a, rTempPoints);
     558                 :            :                             }
     559                 :            : 
     560         [ +  + ]:        275 :                             for(sal_uInt32 b(a + 1L); b < nEdgeCount; b++)
     561                 :            :                             {
     562         [ +  - ]:        215 :                                 rCandidate.getBezierSegment(b, aCubicB);
     563         [ +  - ]:        215 :                                 aCubicB.testAndSolveTrivialBezier();
     564         [ +  - ]:        215 :                                 const B2DRange aRangeB(aCubicB.getRange());
     565                 :            : 
     566                 :            :                                 // only overlapping segments need to be tested
     567                 :            :                                 // consecutive segments touch of course
     568                 :        215 :                                 bool bOverlap = false;
     569         [ +  + ]:        215 :                                 if( b > a+1)
     570         [ +  - ]:        155 :                                     bOverlap = aRangeA.overlaps(aRangeB);
     571                 :            :                                 else
     572         [ +  - ]:         60 :                                     bOverlap = aRangeA.overlapsMore(aRangeB);
     573         [ +  + ]:        215 :                                 if( bOverlap)
     574                 :            :                                 {
     575         [ +  - ]:         25 :                                     const bool bEdgeBIsCurve(aCubicB.isBezier());
     576 [ -  + ][ #  # ]:         25 :                                     if(bEdgeAIsCurve && bEdgeBIsCurve)
     577                 :            :                                     {
     578                 :            :                                         // test for bezier-bezier cuts
     579         [ #  # ]:          0 :                                         findEdgeCutsTwoBeziers(aCubicA, aCubicB, a, b, rTempPoints, rTempPoints);
     580                 :            :                                     }
     581         [ -  + ]:         25 :                                     else if(bEdgeAIsCurve)
     582                 :            :                                     {
     583                 :            :                                         // test for bezier-edge cuts
     584         [ #  # ]:          0 :                                         findEdgeCutsBezierAndEdge(aCubicA, aCubicB.getStartPoint(), aCubicB.getEndPoint(), a, b, rTempPoints, rTempPoints);
     585                 :            :                                     }
     586         [ -  + ]:         25 :                                     else if(bEdgeBIsCurve)
     587                 :            :                                     {
     588                 :            :                                         // test for bezier-edge cuts
     589         [ #  # ]:          0 :                                         findEdgeCutsBezierAndEdge(aCubicB, aCubicA.getStartPoint(), aCubicA.getEndPoint(), b, a, rTempPoints, rTempPoints);
     590                 :            :                                     }
     591                 :            :                                     else
     592                 :            :                                     {
     593                 :            :                                         // test for simple edge-edge cuts
     594                 :            :                                         findEdgeCutsTwoEdges(aCubicA.getStartPoint(), aCubicA.getEndPoint(), aCubicB.getStartPoint(), aCubicB.getEndPoint(),
     595         [ +  - ]:         25 :                                             a, b, rTempPoints, rTempPoints);
     596                 :            :                                     }
     597                 :            :                                 }
     598                 :            :                             }
     599 [ +  - ][ +  - ]:         10 :                         }
     600                 :            :                     }
     601                 :            :                     else
     602                 :            :                     {
     603         [ +  - ]:       2333 :                         B2DPoint aCurrA(rCandidate.getB2DPoint(0L));
     604                 :            : 
     605         [ +  + ]:      11823 :                         for(sal_uInt32 a(0L); a < nEdgeCount - 1L; a++)
     606                 :            :                         {
     607 [ +  - ][ +  - ]:       9490 :                             const B2DPoint aNextA(rCandidate.getB2DPoint(a + 1L == nPointCount ? 0L : a + 1L));
     608         [ +  - ]:       9490 :                             const B2DRange aRangeA(aCurrA, aNextA);
     609         [ +  - ]:       9490 :                             B2DPoint aCurrB(rCandidate.getB2DPoint(a + 1L));
     610                 :            : 
     611         [ +  + ]:      46870 :                             for(sal_uInt32 b(a + 1L); b < nEdgeCount; b++)
     612                 :            :                             {
     613 [ +  + ][ +  - ]:      37380 :                                 const B2DPoint aNextB(rCandidate.getB2DPoint(b + 1L == nPointCount ? 0L : b + 1L));
     614         [ +  - ]:      37380 :                                 const B2DRange aRangeB(aCurrB, aNextB);
     615                 :            : 
     616                 :            :                                 // consecutive segments touch of course
     617                 :      37380 :                                 bool bOverlap = false;
     618         [ +  + ]:      37380 :                                 if( b > a+1)
     619         [ +  - ]:      27890 :                                     bOverlap = aRangeA.overlaps(aRangeB);
     620                 :            :                                 else
     621         [ +  - ]:       9490 :                                     bOverlap = aRangeA.overlapsMore(aRangeB);
     622         [ +  + ]:      37380 :                                 if( bOverlap)
     623                 :            :                                 {
     624         [ +  - ]:       2410 :                                     findEdgeCutsTwoEdges(aCurrA, aNextA, aCurrB, aNextB, a, b, rTempPoints, rTempPoints);
     625                 :            :                                 }
     626                 :            : 
     627                 :            :                                 // prepare next step
     628                 :      37380 :                                 aCurrB = aNextB;
     629                 :      37380 :                             }
     630                 :            : 
     631                 :            :                             // prepare next step
     632                 :       9490 :                             aCurrA = aNextA;
     633                 :      11823 :                         }
     634                 :            :                     }
     635                 :            :                 }
     636                 :            :             }
     637                 :       2343 :         }
     638                 :            : 
     639                 :            :         ////////////////////////////////////////////////////////////////////////////////
     640                 :            : 
     641                 :            :     } // end of anonymous namespace
     642                 :            : } // end of namespace basegfx
     643                 :            : 
     644                 :            : //////////////////////////////////////////////////////////////////////////////
     645                 :            : 
     646                 :            : namespace basegfx
     647                 :            : {
     648                 :            :     namespace
     649                 :            :     {
     650                 :            :         ////////////////////////////////////////////////////////////////////////////////
     651                 :            : 
     652                 :      23200 :         void findTouchesOnEdge(
     653                 :            :             const B2DPoint& rCurr, const B2DPoint& rNext, const B2DPolygon& rPointPolygon,
     654                 :            :             sal_uInt32 nInd, temporaryPointVector& rTempPoints)
     655                 :            :         {
     656                 :            :             // find out if points from rPointPolygon are positioned on given edge. If Yes, add
     657                 :            :             // points there to represent touches (which may be enter or leave nodes later).
     658                 :      23200 :             const sal_uInt32 nPointCount(rPointPolygon.count());
     659                 :            : 
     660         [ +  - ]:      23200 :             if(nPointCount)
     661                 :            :             {
     662         [ +  - ]:      23200 :                 const B2DRange aRange(rCurr, rNext);
     663                 :      23200 :                 const B2DVector aEdgeVector(rNext - rCurr);
     664                 :      23200 :                 B2DVector aNormalizedEdgeVector(aEdgeVector);
     665         [ +  - ]:      23200 :                 aNormalizedEdgeVector.normalize();
     666                 :      23200 :                 bool bTestUsingX(fabs(aEdgeVector.getX()) > fabs(aEdgeVector.getY()));
     667                 :            : 
     668         [ +  + ]:     143389 :                 for(sal_uInt32 a(0L); a < nPointCount; a++)
     669                 :            :                 {
     670         [ +  - ]:     120189 :                     const B2DPoint aTestPoint(rPointPolygon.getB2DPoint(a));
     671                 :            : 
     672 [ +  - ][ +  + ]:     120189 :                     if(aRange.isInside(aTestPoint))
     673                 :            :                     {
     674 [ +  + ][ +  + ]:      26787 :                         if(!aTestPoint.equal(rCurr) && !aTestPoint.equal(rNext))
                 [ +  + ]
     675                 :            :                         {
     676                 :        757 :                             const B2DVector aTestVector(aTestPoint - rCurr);
     677                 :            : 
     678 [ +  + ][ +  - ]:        757 :                             if(areParallel(aNormalizedEdgeVector, aTestVector))
     679                 :            :                             {
     680                 :            :                                 const double fCut((bTestUsingX)
     681                 :         84 :                                     ? aTestVector.getX() / aEdgeVector.getX()
     682         [ +  + ]:        488 :                                     : aTestVector.getY() / aEdgeVector.getY());
     683                 :        404 :                                 const double fZero(0.0);
     684                 :        404 :                                 const double fOne(1.0);
     685                 :            : 
     686 [ +  - ][ +  - ]:        404 :                                 if(fTools::more(fCut, fZero) && fTools::less(fCut, fOne))
                 [ +  - ]
     687                 :            :                                 {
     688         [ +  - ]:        404 :                                     rTempPoints.push_back(temporaryPoint(aTestPoint, nInd, fCut));
     689                 :            :                                 }
     690                 :        757 :                             }
     691                 :            :                         }
     692                 :            :                     }
     693                 :     143389 :                 }
     694                 :            :             }
     695                 :      23200 :         }
     696                 :            : 
     697                 :            :         ////////////////////////////////////////////////////////////////////////////////
     698                 :            : 
     699                 :         20 :         void findTouchesOnCurve(
     700                 :            :             const B2DCubicBezier& rCubicA, const B2DPolygon& rPointPolygon,
     701                 :            :             sal_uInt32 nInd, temporaryPointVector& rTempPoints)
     702                 :            :         {
     703                 :            :             // find all points from rPointPolygon which touch the given bezier segment. Add an entry
     704                 :            :             // for each touch to the given pointVector. The cut for that entry is the relative position on
     705                 :            :             // the given bezier segment.
     706         [ +  - ]:         20 :             B2DPolygon aTempPolygon;
     707         [ +  - ]:         20 :             temporaryPointVector aTempPointVector;
     708                 :            : 
     709                 :            :             // create subdivided polygon and find cuts on it
     710                 :            :             // Keep adaptiveSubdivideByCount due to needed quality
     711         [ +  - ]:         20 :             aTempPolygon.reserve(SUBDIVIDE_FOR_CUT_TEST_COUNT + 8);
     712         [ +  - ]:         20 :             aTempPolygon.append(rCubicA.getStartPoint());
     713         [ +  - ]:         20 :             rCubicA.adaptiveSubdivideByCount(aTempPolygon, SUBDIVIDE_FOR_CUT_TEST_COUNT);
     714         [ +  - ]:         20 :             findTouches(aTempPolygon, rPointPolygon, aTempPointVector);
     715                 :            : 
     716         [ -  + ]:         20 :             if(!aTempPointVector.empty())
     717                 :            :             {
     718                 :            :                 // adapt tempVector entries to segment
     719         [ #  # ]:          0 :                 adaptAndTransferCutsWithBezierSegment(aTempPointVector, aTempPolygon, nInd, rTempPoints);
     720         [ +  - ]:         20 :             }
     721                 :         20 :         }
     722                 :            : 
     723                 :            :         ////////////////////////////////////////////////////////////////////////////////
     724                 :            : 
     725                 :       4589 :         void findTouches(const B2DPolygon& rEdgePolygon, const B2DPolygon& rPointPolygon, temporaryPointVector& rTempPoints)
     726                 :            :         {
     727                 :            :             // find out if points from rPointPolygon touch edges from rEdgePolygon. If yes,
     728                 :            :             // add entries to rTempPoints
     729                 :       4589 :             const sal_uInt32 nPointCount(rPointPolygon.count());
     730                 :       4589 :             const sal_uInt32 nEdgePointCount(rEdgePolygon.count());
     731                 :            : 
     732 [ +  - ][ +  - ]:       4589 :             if(nPointCount && nEdgePointCount)
     733                 :            :             {
     734 [ +  - ][ +  + ]:       4589 :                 const sal_uInt32 nEdgeCount(rEdgePolygon.isClosed() ? nEdgePointCount : nEdgePointCount - 1L);
     735         [ +  - ]:       4589 :                 B2DPoint aCurr(rEdgePolygon.getB2DPoint(0));
     736                 :            : 
     737         [ +  + ]:      27893 :                 for(sal_uInt32 a(0L); a < nEdgeCount; a++)
     738                 :            :                 {
     739                 :      23304 :                     const sal_uInt32 nNextIndex((a + 1) % nEdgePointCount);
     740         [ +  - ]:      23304 :                     const B2DPoint aNext(rEdgePolygon.getB2DPoint(nNextIndex));
     741                 :            : 
     742         [ +  + ]:      23304 :                     if(!aCurr.equal(aNext))
     743                 :            :                     {
     744                 :      23220 :                         bool bHandleAsSimpleEdge(true);
     745                 :            : 
     746 [ +  - ][ +  + ]:      23220 :                         if(rEdgePolygon.areControlPointsUsed())
     747                 :            :                         {
     748         [ +  - ]:        140 :                             const B2DPoint aNextControlPoint(rEdgePolygon.getNextControlPoint(a));
     749         [ +  - ]:        140 :                             const B2DPoint aPrevControlPoint(rEdgePolygon.getPrevControlPoint(nNextIndex));
     750 [ +  + ][ -  + ]:        140 :                             const bool bEdgeIsCurve(!aNextControlPoint.equal(aCurr) || !aPrevControlPoint.equal(aNext));
     751                 :            : 
     752         [ +  + ]:        140 :                             if(bEdgeIsCurve)
     753                 :            :                             {
     754                 :         20 :                                 bHandleAsSimpleEdge = false;
     755         [ +  - ]:         20 :                                 const B2DCubicBezier aCubicA(aCurr, aNextControlPoint, aPrevControlPoint, aNext);
     756 [ +  - ][ +  - ]:         20 :                                 findTouchesOnCurve(aCubicA, rPointPolygon, a, rTempPoints);
     757                 :        140 :                             }
     758                 :            :                         }
     759                 :            : 
     760         [ +  + ]:      23220 :                         if(bHandleAsSimpleEdge)
     761                 :            :                         {
     762         [ +  - ]:      23200 :                             findTouchesOnEdge(aCurr, aNext, rPointPolygon, a, rTempPoints);
     763                 :            :                         }
     764                 :            :                     }
     765                 :            : 
     766                 :            :                     // next step
     767                 :      23304 :                     aCurr = aNext;
     768                 :      27893 :                 }
     769                 :            :             }
     770                 :       4589 :         }
     771                 :            : 
     772                 :            :         ////////////////////////////////////////////////////////////////////////////////
     773                 :            : 
     774                 :            :     } // end of anonymous namespace
     775                 :            : } // end of namespace basegfx
     776                 :            : 
     777                 :            : //////////////////////////////////////////////////////////////////////////////
     778                 :            : 
     779                 :            : namespace basegfx
     780                 :            : {
     781                 :            :     namespace
     782                 :            :     {
     783                 :            :         ////////////////////////////////////////////////////////////////////////////////
     784                 :            : 
     785                 :       1118 :         void findCuts(const B2DPolygon& rCandidateA, const B2DPolygon& rCandidateB, temporaryPointVector& rTempPointsA, temporaryPointVector& rTempPointsB)
     786                 :            :         {
     787                 :            :             // find out if edges from both polygons cut. If so, add entries to rTempPoints which
     788                 :            :             // should be added to the polygons accordingly
     789                 :       1118 :             const sal_uInt32 nPointCountA(rCandidateA.count());
     790                 :       1118 :             const sal_uInt32 nPointCountB(rCandidateB.count());
     791                 :            : 
     792 [ +  - ][ +  - ]:       1118 :             if(nPointCountA && nPointCountB)
     793                 :            :             {
     794         [ +  - ]:       1118 :                 const sal_uInt32 nEdgeCountA(rCandidateA.isClosed() ? nPointCountA : nPointCountA - 1L);
     795         [ +  - ]:       1118 :                 const sal_uInt32 nEdgeCountB(rCandidateB.isClosed() ? nPointCountB : nPointCountB - 1L);
     796                 :            : 
     797 [ +  - ][ +  - ]:       1118 :                 if(nEdgeCountA && nEdgeCountB)
     798                 :            :                 {
     799 [ +  + ][ -  + ]:       1118 :                     const bool bCurvesInvolved(rCandidateA.areControlPointsUsed() || rCandidateB.areControlPointsUsed());
     800                 :            : 
     801         [ +  + ]:       1118 :                     if(bCurvesInvolved)
     802                 :            :                     {
     803         [ +  - ]:          5 :                         B2DCubicBezier aCubicA;
     804         [ +  - ]:          5 :                         B2DCubicBezier aCubicB;
     805                 :            : 
     806         [ +  + ]:         35 :                         for(sal_uInt32 a(0L); a < nEdgeCountA; a++)
     807                 :            :                         {
     808         [ +  - ]:         30 :                             rCandidateA.getBezierSegment(a, aCubicA);
     809         [ +  - ]:         30 :                             aCubicA.testAndSolveTrivialBezier();
     810         [ +  - ]:         30 :                             const bool bEdgeAIsCurve(aCubicA.isBezier());
     811         [ +  - ]:         30 :                             const B2DRange aRangeA(aCubicA.getRange());
     812                 :            : 
     813         [ +  + ]:        270 :                             for(sal_uInt32 b(0L); b < nEdgeCountB; b++)
     814                 :            :                             {
     815         [ +  - ]:        240 :                                 rCandidateB.getBezierSegment(b, aCubicB);
     816         [ +  - ]:        240 :                                 aCubicB.testAndSolveTrivialBezier();
     817         [ +  - ]:        240 :                                 const B2DRange aRangeB(aCubicB.getRange());
     818                 :            : 
     819                 :            :                                 // consecutive segments touch of course
     820                 :        240 :                                 bool bOverlap = false;
     821         [ +  + ]:        240 :                                 if( b > a+1)
     822         [ +  - ]:        105 :                                     bOverlap = aRangeA.overlaps(aRangeB);
     823                 :            :                                 else
     824         [ +  - ]:        135 :                                     bOverlap = aRangeA.overlapsMore(aRangeB);
     825         [ +  + ]:        240 :                                 if( bOverlap)
     826                 :            :                                 {
     827         [ +  - ]:         45 :                                     const bool bEdgeBIsCurve(aCubicB.isBezier());
     828 [ +  + ][ +  - ]:         45 :                                     if(bEdgeAIsCurve && bEdgeBIsCurve)
     829                 :            :                                     {
     830                 :            :                                         // test for bezier-bezier cuts
     831         [ +  - ]:          5 :                                         findEdgeCutsTwoBeziers(aCubicA, aCubicB, a, b, rTempPointsA, rTempPointsB);
     832                 :            :                                     }
     833         [ -  + ]:         40 :                                     else if(bEdgeAIsCurve)
     834                 :            :                                     {
     835                 :            :                                         // test for bezier-edge cuts
     836         [ #  # ]:          0 :                                         findEdgeCutsBezierAndEdge(aCubicA, aCubicB.getStartPoint(), aCubicB.getEndPoint(), a, b, rTempPointsA, rTempPointsB);
     837                 :            :                                     }
     838         [ -  + ]:         40 :                                     else if(bEdgeBIsCurve)
     839                 :            :                                     {
     840                 :            :                                         // test for bezier-edge cuts
     841         [ #  # ]:          0 :                                         findEdgeCutsBezierAndEdge(aCubicB, aCubicA.getStartPoint(), aCubicA.getEndPoint(), b, a, rTempPointsB, rTempPointsA);
     842                 :            :                                     }
     843                 :            :                                     else
     844                 :            :                                     {
     845                 :            :                                         // test for simple edge-edge cuts
     846                 :            :                                         findEdgeCutsTwoEdges(aCubicA.getStartPoint(), aCubicA.getEndPoint(), aCubicB.getStartPoint(), aCubicB.getEndPoint(),
     847         [ +  - ]:         45 :                                             a, b, rTempPointsA, rTempPointsB);
     848                 :            :                                     }
     849                 :            :                                 }
     850                 :            :                             }
     851 [ +  - ][ +  - ]:          5 :                         }
     852                 :            :                     }
     853                 :            :                     else
     854                 :            :                     {
     855         [ +  - ]:       1113 :                         B2DPoint aCurrA(rCandidateA.getB2DPoint(0L));
     856                 :            : 
     857         [ +  + ]:       7322 :                         for(sal_uInt32 a(0L); a < nEdgeCountA; a++)
     858                 :            :                         {
     859 [ +  + ][ +  - ]:       6209 :                             const B2DPoint aNextA(rCandidateA.getB2DPoint(a + 1L == nPointCountA ? 0L : a + 1L));
     860         [ +  - ]:       6209 :                             const B2DRange aRangeA(aCurrA, aNextA);
     861         [ +  - ]:       6209 :                             B2DPoint aCurrB(rCandidateB.getB2DPoint(0L));
     862                 :            : 
     863         [ +  + ]:      32230 :                             for(sal_uInt32 b(0L); b < nEdgeCountB; b++)
     864                 :            :                             {
     865 [ +  + ][ +  - ]:      26021 :                                 const B2DPoint aNextB(rCandidateB.getB2DPoint(b + 1L == nPointCountB ? 0L : b + 1L));
     866         [ +  - ]:      26021 :                                 const B2DRange aRangeB(aCurrB, aNextB);
     867                 :            : 
     868                 :            :                                 // consecutive segments touch of course
     869                 :      26021 :                                 bool bOverlap = false;
     870         [ +  + ]:      26021 :                                 if( b > a+1)
     871         [ +  - ]:       4284 :                                     bOverlap = aRangeA.overlaps(aRangeB);
     872                 :            :                                 else
     873         [ +  - ]:      21737 :                                     bOverlap = aRangeA.overlapsMore(aRangeB);
     874         [ +  + ]:      26021 :                                 if( bOverlap)
     875                 :            :                                 {
     876                 :            :                                     // test for simple edge-edge cuts
     877         [ +  - ]:       2660 :                                     findEdgeCutsTwoEdges(aCurrA, aNextA, aCurrB, aNextB, a, b, rTempPointsA, rTempPointsB);
     878                 :            :                                 }
     879                 :            : 
     880                 :            :                                 // prepare next step
     881                 :      26021 :                                 aCurrB = aNextB;
     882                 :      26021 :                             }
     883                 :            : 
     884                 :            :                             // prepare next step
     885                 :       6209 :                             aCurrA = aNextA;
     886                 :       7322 :                         }
     887                 :            :                     }
     888                 :            :                 }
     889                 :            :             }
     890                 :       1118 :         }
     891                 :            : 
     892                 :            :         ////////////////////////////////////////////////////////////////////////////////
     893                 :            : 
     894                 :            :     } // end of anonymous namespace
     895                 :            : } // end of namespace basegfx
     896                 :            : 
     897                 :            : //////////////////////////////////////////////////////////////////////////////
     898                 :            : 
     899                 :            : namespace basegfx
     900                 :            : {
     901                 :            :     namespace tools
     902                 :            :     {
     903                 :            :         ////////////////////////////////////////////////////////////////////////////////
     904                 :            : 
     905                 :       2333 :         B2DPolygon addPointsAtCutsAndTouches(const B2DPolygon& rCandidate)
     906                 :            :         {
     907         [ +  - ]:       2333 :             if(rCandidate.count())
     908                 :            :             {
     909         [ +  - ]:       2333 :                 temporaryPointVector aTempPoints;
     910                 :            : 
     911         [ +  - ]:       2333 :                 findTouches(rCandidate, rCandidate, aTempPoints);
     912         [ +  - ]:       2333 :                 findCuts(rCandidate, aTempPoints);
     913                 :            : 
     914         [ +  - ]:       2333 :                 return mergeTemporaryPointsAndPolygon(rCandidate, aTempPoints);
     915                 :            :             }
     916                 :            :             else
     917                 :            :             {
     918                 :       2333 :                 return rCandidate;
     919                 :            :             }
     920                 :            :         }
     921                 :            : 
     922                 :            :         ////////////////////////////////////////////////////////////////////////////////
     923                 :            : 
     924                 :       1116 :         B2DPolyPolygon addPointsAtCutsAndTouches(const B2DPolyPolygon& rCandidate, bool bSelfIntersections)
     925                 :            :         {
     926                 :       1116 :             const sal_uInt32 nCount(rCandidate.count());
     927                 :            : 
     928         [ +  - ]:       1116 :             if(nCount)
     929                 :            :             {
     930         [ +  - ]:       1116 :                 B2DPolyPolygon aRetval;
     931                 :            : 
     932         [ +  + ]:       1116 :                 if(1L == nCount)
     933                 :            :                 {
     934         [ +  - ]:         18 :                     if(bSelfIntersections)
     935                 :            :                     {
     936                 :            :                         // remove self intersections
     937 [ +  - ][ +  - ]:         18 :                         aRetval.append(addPointsAtCutsAndTouches(rCandidate.getB2DPolygon(0L)));
         [ +  - ][ +  - ]
                 [ +  - ]
     938                 :            :                     }
     939                 :            :                     else
     940                 :            :                     {
     941                 :            :                         // copy source
     942         [ #  # ]:          0 :                         aRetval = rCandidate;
     943                 :            :                     }
     944                 :            :                 }
     945                 :            :                 else
     946                 :            :                 {
     947                 :            :                     // first solve self cuts and self touches for all contained single polygons
     948 [ +  - ][ +  - ]:       3373 :                     temporaryPolygonData *pTempData = new temporaryPolygonData[nCount];
           [ +  +  #  #  
                   #  # ]
     949                 :            :                     sal_uInt32 a, b;
     950                 :            : 
     951         [ +  + ]:       3373 :                     for(a = 0L; a < nCount; a++)
     952                 :            :                     {
     953         [ +  - ]:       2275 :                         if(bSelfIntersections)
     954                 :            :                         {
     955                 :            :                             // use polygons with solved self intersections
     956 [ +  - ][ +  - ]:       2275 :                             pTempData[a].setPolygon(addPointsAtCutsAndTouches(rCandidate.getB2DPolygon(a)));
         [ +  - ][ +  - ]
                 [ +  - ]
     957                 :            :                         }
     958                 :            :                         else
     959                 :            :                         {
     960                 :            :                             // copy given polygons
     961 [ #  # ][ #  # ]:          0 :                             pTempData[a].setPolygon(rCandidate.getB2DPolygon(a));
                 [ #  # ]
     962                 :            :                         }
     963                 :            :                     }
     964                 :            : 
     965                 :            :                     // now cuts and touches between the polygons
     966         [ +  + ]:       3373 :                     for(a = 0L; a < nCount; a++)
     967                 :            :                     {
     968         [ +  + ]:       7096 :                         for(b = 0L; b < nCount; b++)
     969                 :            :                         {
     970         [ +  + ]:       4821 :                             if(a != b)
     971                 :            :                             {
     972                 :            :                                 // look for touches, compare each edge polygon to all other points
     973 [ +  - ][ +  + ]:       2546 :                                 if(pTempData[a].getRange().overlaps(pTempData[b].getRange()))
     974                 :            :                                 {
     975         [ +  - ]:       2236 :                                     findTouches(pTempData[a].getPolygon(), pTempData[b].getPolygon(), pTempData[a].getTemporaryPointVector());
     976                 :            :                                 }
     977                 :            :                             }
     978                 :            : 
     979         [ +  + ]:       4821 :                             if(a < b)
     980                 :            :                             {
     981                 :            :                                 // look for cuts, compare each edge polygon to following ones
     982 [ +  - ][ +  + ]:       1273 :                                 if(pTempData[a].getRange().overlaps(pTempData[b].getRange()))
     983                 :            :                                 {
     984         [ +  - ]:       1118 :                                     findCuts(pTempData[a].getPolygon(), pTempData[b].getPolygon(), pTempData[a].getTemporaryPointVector(), pTempData[b].getTemporaryPointVector());
     985                 :            :                                 }
     986                 :            :                             }
     987                 :            :                         }
     988                 :            :                     }
     989                 :            : 
     990                 :            :                     // consolidate the result
     991         [ +  + ]:       3373 :                     for(a = 0L; a < nCount; a++)
     992                 :            :                     {
     993 [ +  - ][ +  - ]:       2275 :                         aRetval.append(mergeTemporaryPointsAndPolygon(pTempData[a].getPolygon(), pTempData[a].getTemporaryPointVector()));
                 [ +  - ]
     994                 :            :                     }
     995                 :            : 
     996 [ +  - ][ +  + ]:       3373 :                     delete[] pTempData;
                 [ +  - ]
     997                 :            :                 }
     998                 :            : 
     999 [ +  - ][ +  - ]:       1116 :                 return aRetval;
    1000                 :            :             }
    1001                 :            :             else
    1002                 :            :             {
    1003                 :       1116 :                 return rCandidate;
    1004                 :            :             }
    1005                 :            :         }
    1006                 :            : 
    1007                 :            :         ////////////////////////////////////////////////////////////////////////////////
    1008                 :            : 
    1009                 :          0 :         B2DPolygon addPointsAtCuts(const B2DPolygon& rCandidate, const B2DPoint& rStart, const B2DPoint& rEnd)
    1010                 :            :         {
    1011                 :          0 :             const sal_uInt32 nCount(rCandidate.count());
    1012                 :            : 
    1013 [ #  # ][ #  # ]:          0 :             if(nCount && !rStart.equal(rEnd))
                 [ #  # ]
    1014                 :            :             {
    1015         [ #  # ]:          0 :                 const B2DRange aPolygonRange(rCandidate.getB2DRange());
    1016         [ #  # ]:          0 :                 const B2DRange aEdgeRange(rStart, rEnd);
    1017                 :            : 
    1018 [ #  # ][ #  # ]:          0 :                 if(aPolygonRange.overlaps(aEdgeRange))
    1019                 :            :                 {
    1020 [ #  # ][ #  # ]:          0 :                     const sal_uInt32 nEdgeCount(rCandidate.isClosed() ? nCount : nCount - 1);
    1021         [ #  # ]:          0 :                     temporaryPointVector aTempPoints;
    1022         [ #  # ]:          0 :                     temporaryPointVector aUnusedTempPoints;
    1023         [ #  # ]:          0 :                     B2DCubicBezier aCubic;
    1024                 :            : 
    1025         [ #  # ]:          0 :                     for(sal_uInt32 a(0); a < nEdgeCount; a++)
    1026                 :            :                     {
    1027         [ #  # ]:          0 :                         rCandidate.getBezierSegment(a, aCubic);
    1028         [ #  # ]:          0 :                         B2DRange aCubicRange(aCubic.getStartPoint(), aCubic.getEndPoint());
    1029                 :            : 
    1030 [ #  # ][ #  # ]:          0 :                         if(aCubic.isBezier())
    1031                 :            :                         {
    1032         [ #  # ]:          0 :                             aCubicRange.expand(aCubic.getControlPointA());
    1033         [ #  # ]:          0 :                             aCubicRange.expand(aCubic.getControlPointB());
    1034                 :            : 
    1035 [ #  # ][ #  # ]:          0 :                             if(aCubicRange.overlaps(aEdgeRange))
    1036                 :            :                             {
    1037         [ #  # ]:          0 :                                 findEdgeCutsBezierAndEdge(aCubic, rStart, rEnd, a, 0, aTempPoints, aUnusedTempPoints);
    1038                 :            :                             }
    1039                 :            :                         }
    1040                 :            :                         else
    1041                 :            :                         {
    1042 [ #  # ][ #  # ]:          0 :                             if(aCubicRange.overlaps(aEdgeRange))
    1043                 :            :                             {
    1044         [ #  # ]:          0 :                                 findEdgeCutsTwoEdges(aCubic.getStartPoint(), aCubic.getEndPoint(), rStart, rEnd, a, 0, aTempPoints, aUnusedTempPoints);
    1045                 :            :                             }
    1046                 :            :                         }
    1047                 :            :                     }
    1048                 :            : 
    1049 [ #  # ][ #  # ]:          0 :                     return mergeTemporaryPointsAndPolygon(rCandidate, aTempPoints);
    1050                 :            :                 }
    1051                 :            :             }
    1052                 :            : 
    1053                 :          0 :             return rCandidate;
    1054                 :            :         }
    1055                 :            : 
    1056                 :            :         ////////////////////////////////////////////////////////////////////////////////
    1057                 :            : 
    1058                 :        802 :         B2DPolygon addPointsAtCuts(const B2DPolygon& rCandidate, const B2DPolyPolygon& rPolyMask)
    1059                 :            :         {
    1060                 :        802 :             const sal_uInt32 nCountA(rCandidate.count());
    1061                 :        802 :             const sal_uInt32 nCountM(rPolyMask.count());
    1062                 :            : 
    1063 [ +  - ][ +  - ]:        802 :             if(nCountA && nCountM)
    1064                 :            :             {
    1065         [ +  - ]:        802 :                 const B2DRange aRangeA(rCandidate.getB2DRange());
    1066         [ +  - ]:        802 :                 const B2DRange aRangeM(rPolyMask.getB2DRange());
    1067                 :            : 
    1068 [ +  - ][ +  - ]:        802 :                 if(aRangeA.overlaps(aRangeM))
    1069                 :            :                 {
    1070 [ +  - ][ -  + ]:        802 :                     const sal_uInt32 nEdgeCountA(rCandidate.isClosed() ? nCountA : nCountA - 1);
    1071         [ +  - ]:        802 :                     temporaryPointVector aTempPointsA;
    1072         [ +  - ]:        802 :                     temporaryPointVector aUnusedTempPointsB;
    1073                 :            : 
    1074         [ +  + ]:       1604 :                     for(sal_uInt32 m(0); m < nCountM; m++)
    1075                 :            :                     {
    1076         [ +  - ]:        802 :                         const B2DPolygon aMask(rPolyMask.getB2DPolygon(m));
    1077         [ +  - ]:        802 :                         const sal_uInt32 nCountB(aMask.count());
    1078                 :            : 
    1079         [ +  - ]:        802 :                         if(nCountB)
    1080                 :            :                         {
    1081         [ +  - ]:        802 :                             B2DCubicBezier aCubicA;
    1082         [ +  - ]:        802 :                             B2DCubicBezier aCubicB;
    1083                 :            : 
    1084         [ +  + ]:       1604 :                             for(sal_uInt32 a(0); a < nEdgeCountA; a++)
    1085                 :            :                             {
    1086         [ +  - ]:        802 :                                 rCandidate.getBezierSegment(a, aCubicA);
    1087         [ +  - ]:        802 :                                 const bool bCubicAIsCurve(aCubicA.isBezier());
    1088         [ +  - ]:        802 :                                 B2DRange aCubicRangeA(aCubicA.getStartPoint(), aCubicA.getEndPoint());
    1089                 :            : 
    1090         [ -  + ]:        802 :                                 if(bCubicAIsCurve)
    1091                 :            :                                 {
    1092         [ #  # ]:          0 :                                     aCubicRangeA.expand(aCubicA.getControlPointA());
    1093         [ #  # ]:          0 :                                     aCubicRangeA.expand(aCubicA.getControlPointB());
    1094                 :            :                                 }
    1095                 :            : 
    1096         [ +  + ]:       4142 :                                 for(sal_uInt32 b(0); b < nCountB; b++)
    1097                 :            :                                 {
    1098         [ +  - ]:       3340 :                                     aMask.getBezierSegment(b, aCubicB);
    1099         [ +  - ]:       3340 :                                     const bool bCubicBIsCurve(aCubicB.isBezier());
    1100         [ +  - ]:       3340 :                                     B2DRange aCubicRangeB(aCubicB.getStartPoint(), aCubicB.getEndPoint());
    1101                 :            : 
    1102         [ -  + ]:       3340 :                                     if(bCubicBIsCurve)
    1103                 :            :                                     {
    1104         [ #  # ]:          0 :                                         aCubicRangeB.expand(aCubicB.getControlPointA());
    1105         [ #  # ]:          0 :                                         aCubicRangeB.expand(aCubicB.getControlPointB());
    1106                 :            :                                     }
    1107                 :            : 
    1108 [ +  - ][ +  + ]:       3340 :                                     if(aCubicRangeA.overlaps(aCubicRangeB))
    1109                 :            :                                     {
    1110 [ -  + ][ #  # ]:       1604 :                                         if(bCubicAIsCurve && bCubicBIsCurve)
    1111                 :            :                                         {
    1112         [ #  # ]:          0 :                                             findEdgeCutsTwoBeziers(aCubicA, aCubicB, a, b, aTempPointsA, aUnusedTempPointsB);
    1113                 :            :                                         }
    1114         [ -  + ]:       1604 :                                         else if(bCubicAIsCurve)
    1115                 :            :                                         {
    1116         [ #  # ]:          0 :                                             findEdgeCutsBezierAndEdge(aCubicA, aCubicB.getStartPoint(), aCubicB.getEndPoint(), a, b, aTempPointsA, aUnusedTempPointsB);
    1117                 :            :                                         }
    1118         [ -  + ]:       1604 :                                         else if(bCubicBIsCurve)
    1119                 :            :                                         {
    1120         [ #  # ]:          0 :                                             findEdgeCutsBezierAndEdge(aCubicB, aCubicA.getStartPoint(), aCubicA.getEndPoint(), b, a, aUnusedTempPointsB, aTempPointsA);
    1121                 :            :                                         }
    1122                 :            :                                         else
    1123                 :            :                                         {
    1124         [ +  - ]:       1604 :                                             findEdgeCutsTwoEdges(aCubicA.getStartPoint(), aCubicA.getEndPoint(), aCubicB.getStartPoint(), aCubicB.getEndPoint(), a, b, aTempPointsA, aUnusedTempPointsB);
    1125                 :            :                                         }
    1126                 :            :                                     }
    1127                 :            :                                 }
    1128 [ +  - ][ +  - ]:        802 :                             }
    1129                 :            :                         }
    1130         [ +  - ]:        802 :                     }
    1131                 :            : 
    1132         [ +  - ]:        802 :                     return mergeTemporaryPointsAndPolygon(rCandidate, aTempPointsA);
    1133                 :            :                 }
    1134                 :            :             }
    1135                 :            : 
    1136                 :        802 :             return rCandidate;
    1137                 :            :         }
    1138                 :            : 
    1139                 :            :         ////////////////////////////////////////////////////////////////////////////////
    1140                 :            : 
    1141                 :            :     } // end of namespace tools
    1142                 :            : } // end of namespace basegfx
    1143                 :            : 
    1144                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10