LCOV - code coverage report
Current view: top level - basegfx/source/polygon - b2dpolypolygontools.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 156 311 50.2 %
Date: 2014-11-03 Functions: 16 29 55.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      21             : #include <osl/diagnose.h>
      22             : #include <basegfx/polygon/b2dpolypolygon.hxx>
      23             : #include <basegfx/polygon/b2dpolygon.hxx>
      24             : #include <basegfx/polygon/b2dpolygontools.hxx>
      25             : #include <basegfx/numeric/ftools.hxx>
      26             : #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
      27             : #include <numeric>
      28             : 
      29             : namespace basegfx
      30             : {
      31             :     namespace tools
      32             :     {
      33        3895 :         B2DPolyPolygon correctOrientations(const B2DPolyPolygon& rCandidate)
      34             :         {
      35        3895 :             B2DPolyPolygon aRetval(rCandidate);
      36        3895 :             const sal_uInt32 nCount(aRetval.count());
      37             : 
      38        7806 :             for(sal_uInt32 a(0L); a < nCount; a++)
      39             :             {
      40        3911 :                 const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
      41        3911 :                 const B2VectorOrientation aOrientation(tools::getOrientation(aCandidate));
      42        3911 :                 sal_uInt32 nDepth(0L);
      43             : 
      44        8290 :                 for(sal_uInt32 b(0L); b < nCount; b++)
      45             :                 {
      46        4379 :                     if(b != a)
      47             :                     {
      48         468 :                         const B2DPolygon aCompare(rCandidate.getB2DPolygon(b));
      49             : 
      50         468 :                         if(tools::isInside(aCompare, aCandidate, true))
      51             :                         {
      52          24 :                             nDepth++;
      53         468 :                         }
      54             :                     }
      55             :                 }
      56             : 
      57        3911 :                 const bool bShallBeHole(1L == (nDepth & 0x00000001));
      58        3911 :                 const bool bIsHole(ORIENTATION_NEGATIVE == aOrientation);
      59             : 
      60        3911 :                 if(bShallBeHole != bIsHole && ORIENTATION_NEUTRAL != aOrientation)
      61             :                 {
      62         121 :                     B2DPolygon aFlipped(aCandidate);
      63         121 :                     aFlipped.flip();
      64         121 :                     aRetval.setB2DPolygon(a, aFlipped);
      65             :                 }
      66        3911 :             }
      67             : 
      68        3895 :             return aRetval;
      69             :         }
      70             : 
      71        3381 :         B2DPolyPolygon correctOutmostPolygon(const B2DPolyPolygon& rCandidate)
      72             :         {
      73        3381 :             const sal_uInt32 nCount(rCandidate.count());
      74             : 
      75        3381 :             if(nCount > 1L)
      76             :             {
      77          96 :                 for(sal_uInt32 a(0L); a < nCount; a++)
      78             :                 {
      79          96 :                     const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
      80          96 :                     sal_uInt32 nDepth(0L);
      81             : 
      82         336 :                     for(sal_uInt32 b(0L); b < nCount; b++)
      83             :                     {
      84         240 :                         if(b != a)
      85             :                         {
      86         144 :                             const B2DPolygon aCompare(rCandidate.getB2DPolygon(b));
      87             : 
      88         144 :                             if(tools::isInside(aCompare, aCandidate, true))
      89             :                             {
      90           0 :                                 nDepth++;
      91         144 :                             }
      92             :                         }
      93             :                     }
      94             : 
      95          96 :                     if(!nDepth)
      96             :                     {
      97          96 :                         B2DPolyPolygon aRetval(rCandidate);
      98             : 
      99          96 :                         if(a != 0L)
     100             :                         {
     101             :                             // exchange polygon a and polygon 0L
     102           0 :                             aRetval.setB2DPolygon(0L, aCandidate);
     103           0 :                             aRetval.setB2DPolygon(a, rCandidate.getB2DPolygon(0L));
     104             :                         }
     105             : 
     106             :                         // exit
     107          96 :                         return aRetval;
     108             :                     }
     109           0 :                 }
     110             :             }
     111             : 
     112        3285 :             return rCandidate;
     113             :         }
     114             : 
     115           0 :         B2DPolyPolygon adaptiveSubdivideByDistance(const B2DPolyPolygon& rCandidate, double fDistanceBound)
     116             :         {
     117           0 :             if(rCandidate.areControlPointsUsed())
     118             :             {
     119           0 :                 const sal_uInt32 nPolygonCount(rCandidate.count());
     120           0 :                 B2DPolyPolygon aRetval;
     121             : 
     122           0 :                 for(sal_uInt32 a(0L); a < nPolygonCount; a++)
     123             :                 {
     124           0 :                     const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
     125             : 
     126           0 :                     if(aCandidate.areControlPointsUsed())
     127             :                     {
     128           0 :                         aRetval.append(tools::adaptiveSubdivideByDistance(aCandidate, fDistanceBound));
     129             :                     }
     130             :                     else
     131             :                     {
     132           0 :                         aRetval.append(aCandidate);
     133             :                     }
     134           0 :                 }
     135             : 
     136           0 :                 return aRetval;
     137             :             }
     138             :             else
     139             :             {
     140           0 :                 return rCandidate;
     141             :             }
     142             :         }
     143             : 
     144        3473 :         B2DPolyPolygon adaptiveSubdivideByAngle(const B2DPolyPolygon& rCandidate, double fAngleBound)
     145             :         {
     146        3473 :             if(rCandidate.areControlPointsUsed())
     147             :             {
     148          66 :                 const sal_uInt32 nPolygonCount(rCandidate.count());
     149          66 :                 B2DPolyPolygon aRetval;
     150             : 
     151         132 :                 for(sal_uInt32 a(0L); a < nPolygonCount; a++)
     152             :                 {
     153          66 :                     const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
     154             : 
     155          66 :                     if(aCandidate.areControlPointsUsed())
     156             :                     {
     157          66 :                         aRetval.append(tools::adaptiveSubdivideByAngle(aCandidate, fAngleBound));
     158             :                     }
     159             :                     else
     160             :                     {
     161           0 :                         aRetval.append(aCandidate);
     162             :                     }
     163          66 :                 }
     164             : 
     165          66 :                 return aRetval;
     166             :             }
     167             :             else
     168             :             {
     169        3407 :                 return rCandidate;
     170             :             }
     171             :         }
     172             : 
     173           0 :         B2DPolyPolygon adaptiveSubdivideByCount(const B2DPolyPolygon& rCandidate, sal_uInt32 nCount)
     174             :         {
     175           0 :             if(rCandidate.areControlPointsUsed())
     176             :             {
     177           0 :                 const sal_uInt32 nPolygonCount(rCandidate.count());
     178           0 :                 B2DPolyPolygon aRetval;
     179             : 
     180           0 :                 for(sal_uInt32 a(0L); a < nPolygonCount; a++)
     181             :                 {
     182           0 :                     const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
     183             : 
     184           0 :                     if(aCandidate.areControlPointsUsed())
     185             :                     {
     186           0 :                         aRetval.append(tools::adaptiveSubdivideByCount(aCandidate, nCount));
     187             :                     }
     188             :                     else
     189             :                     {
     190           0 :                         aRetval.append(aCandidate);
     191             :                     }
     192           0 :                 }
     193             : 
     194           0 :                 return aRetval;
     195             :             }
     196             :             else
     197             :             {
     198           0 :                 return rCandidate;
     199             :             }
     200             :         }
     201             : 
     202        1108 :         bool isInside(const B2DPolyPolygon& rCandidate, const B2DPoint& rPoint, bool bWithBorder)
     203             :         {
     204        1108 :             const sal_uInt32 nPolygonCount(rCandidate.count());
     205             : 
     206        1108 :             if(1L == nPolygonCount)
     207             :             {
     208        1108 :                 return isInside(rCandidate.getB2DPolygon(0L), rPoint, bWithBorder);
     209             :             }
     210             :             else
     211             :             {
     212           0 :                 sal_Int32 nInsideCount(0L);
     213             : 
     214           0 :                 for(sal_uInt32 a(0L); a < nPolygonCount; a++)
     215             :                 {
     216           0 :                     const B2DPolygon aPolygon(rCandidate.getB2DPolygon(a));
     217           0 :                     const bool bInside(isInside(aPolygon, rPoint, bWithBorder));
     218             : 
     219           0 :                     if(bInside)
     220             :                     {
     221           0 :                         nInsideCount++;
     222             :                     }
     223           0 :                 }
     224             : 
     225           0 :                 return (nInsideCount % 2L);
     226             :             }
     227             :         }
     228             : 
     229     4997667 :         B2DRange getRange(const B2DPolyPolygon& rCandidate)
     230             :         {
     231     4997667 :             B2DRange aRetval;
     232     4997667 :             const sal_uInt32 nPolygonCount(rCandidate.count());
     233             : 
     234    10155336 :             for(sal_uInt32 a(0L); a < nPolygonCount; a++)
     235             :             {
     236     5157669 :                 B2DPolygon aCandidate = rCandidate.getB2DPolygon(a);
     237     5157669 :                 aRetval.expand(tools::getRange(aCandidate));
     238     5157669 :             }
     239             : 
     240     4997667 :             return aRetval;
     241             :         }
     242             : 
     243           0 :         double getSignedArea(const B2DPolyPolygon& rCandidate)
     244             :         {
     245           0 :             double fRetval(0.0);
     246           0 :             const sal_uInt32 nPolygonCount(rCandidate.count());
     247             : 
     248           0 :             for(sal_uInt32 a(0L); a < nPolygonCount; a++)
     249             :             {
     250           0 :                 const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
     251             : 
     252           0 :                 fRetval += tools::getSignedArea(aCandidate);
     253           0 :             }
     254             : 
     255           0 :             return fRetval;
     256             :         }
     257             : 
     258           0 :         double getArea(const B2DPolyPolygon& rCandidate)
     259             :         {
     260           0 :             return fabs(getSignedArea(rCandidate));
     261             :         }
     262             : 
     263           0 :         void applyLineDashing(const B2DPolyPolygon& rCandidate, const ::std::vector<double>& rDotDashArray, B2DPolyPolygon* pLineTarget, B2DPolyPolygon* pGapTarget, double fFullDashDotLen)
     264             :         {
     265           0 :             if(0.0 == fFullDashDotLen && rDotDashArray.size())
     266             :             {
     267             :                 // calculate fFullDashDotLen from rDotDashArray
     268           0 :                 fFullDashDotLen = ::std::accumulate(rDotDashArray.begin(), rDotDashArray.end(), 0.0);
     269             :             }
     270             : 
     271           0 :             if(rCandidate.count() && fFullDashDotLen > 0.0)
     272             :             {
     273           0 :                 B2DPolyPolygon aLineTarget, aGapTarget;
     274             : 
     275           0 :                 for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
     276             :                 {
     277           0 :                     const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
     278             : 
     279             :                     applyLineDashing(
     280             :                         aCandidate,
     281             :                         rDotDashArray,
     282             :                         pLineTarget ? &aLineTarget : 0,
     283             :                         pGapTarget ? &aGapTarget : 0,
     284           0 :                         fFullDashDotLen);
     285             : 
     286           0 :                     if(pLineTarget)
     287             :                     {
     288           0 :                         pLineTarget->append(aLineTarget);
     289             :                     }
     290             : 
     291           0 :                     if(pGapTarget)
     292             :                     {
     293           0 :                         pGapTarget->append(aGapTarget);
     294             :                     }
     295           0 :                 }
     296             :             }
     297           0 :         }
     298             : 
     299          10 :         bool isInEpsilonRange(const B2DPolyPolygon& rCandidate, const B2DPoint& rTestPosition, double fDistance)
     300             :         {
     301          10 :             const sal_uInt32 nPolygonCount(rCandidate.count());
     302             : 
     303          14 :             for(sal_uInt32 a(0L); a < nPolygonCount; a++)
     304             :             {
     305          10 :                 B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
     306             : 
     307          10 :                 if(isInEpsilonRange(aCandidate, rTestPosition, fDistance))
     308             :                 {
     309           6 :                     return true;
     310             :                 }
     311           4 :             }
     312             : 
     313           4 :             return false;
     314             :         }
     315             : 
     316       16700 :         B3DPolyPolygon createB3DPolyPolygonFromB2DPolyPolygon(const B2DPolyPolygon& rCandidate, double fZCoordinate)
     317             :         {
     318       16700 :             const sal_uInt32 nPolygonCount(rCandidate.count());
     319       16700 :             B3DPolyPolygon aRetval;
     320             : 
     321       38368 :             for(sal_uInt32 a(0L); a < nPolygonCount; a++)
     322             :             {
     323       21668 :                 B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
     324             : 
     325       21668 :                 aRetval.append(createB3DPolygonFromB2DPolygon(aCandidate, fZCoordinate));
     326       21668 :             }
     327             : 
     328       16700 :             return aRetval;
     329             :         }
     330             : 
     331        4076 :         B2DPolyPolygon createB2DPolyPolygonFromB3DPolyPolygon(const B3DPolyPolygon& rCandidate, const B3DHomMatrix& rMat)
     332             :         {
     333        4076 :             const sal_uInt32 nPolygonCount(rCandidate.count());
     334        4076 :             B2DPolyPolygon aRetval;
     335             : 
     336        8296 :             for(sal_uInt32 a(0L); a < nPolygonCount; a++)
     337             :             {
     338        4220 :                 B3DPolygon aCandidate(rCandidate.getB3DPolygon(a));
     339             : 
     340        4220 :                 aRetval.append(createB2DPolygonFromB3DPolygon(aCandidate, rMat));
     341        4220 :             }
     342             : 
     343        4076 :             return aRetval;
     344             :         }
     345             : 
     346           0 :         double getSmallestDistancePointToPolyPolygon(const B2DPolyPolygon& rCandidate, const B2DPoint& rTestPoint, sal_uInt32& rPolygonIndex, sal_uInt32& rEdgeIndex, double& rCut)
     347             :         {
     348           0 :             double fRetval(DBL_MAX);
     349           0 :             const double fZero(0.0);
     350           0 :             const sal_uInt32 nPolygonCount(rCandidate.count());
     351             : 
     352           0 :             for(sal_uInt32 a(0L); a < nPolygonCount; a++)
     353             :             {
     354           0 :                 const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
     355             :                 sal_uInt32 nNewEdgeIndex;
     356           0 :                 double fNewCut(0.0);
     357           0 :                 const double fNewDistance(getSmallestDistancePointToPolygon(aCandidate, rTestPoint, nNewEdgeIndex, fNewCut));
     358             : 
     359           0 :                 if(DBL_MAX == fRetval || fNewDistance < fRetval)
     360             :                 {
     361           0 :                     fRetval = fNewDistance;
     362           0 :                     rPolygonIndex = a;
     363           0 :                     rEdgeIndex = nNewEdgeIndex;
     364           0 :                     rCut = fNewCut;
     365             : 
     366           0 :                     if(fTools::equal(fRetval, fZero))
     367             :                     {
     368             :                         // already found zero distance, cannot get better. Ensure numerical zero value and end loop.
     369           0 :                         fRetval = 0.0;
     370           0 :                         break;
     371             :                     }
     372             :                 }
     373           0 :             }
     374             : 
     375           0 :             return fRetval;
     376             :         }
     377             : 
     378           0 :         B2DPolyPolygon distort(const B2DPolyPolygon& rCandidate, const B2DRange& rOriginal, const B2DPoint& rTopLeft, const B2DPoint& rTopRight, const B2DPoint& rBottomLeft, const B2DPoint& rBottomRight)
     379             :         {
     380           0 :             const sal_uInt32 nPolygonCount(rCandidate.count());
     381           0 :             B2DPolyPolygon aRetval;
     382             : 
     383           0 :             for(sal_uInt32 a(0L); a < nPolygonCount; a++)
     384             :             {
     385           0 :                 const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
     386             : 
     387           0 :                 aRetval.append(distort(aCandidate, rOriginal, rTopLeft, rTopRight, rBottomLeft, rBottomRight));
     388           0 :             }
     389             : 
     390           0 :             return aRetval;
     391             :         }
     392             : 
     393          40 :         B2DPolyPolygon expandToCurve(const B2DPolyPolygon& rCandidate)
     394             :         {
     395          40 :             const sal_uInt32 nPolygonCount(rCandidate.count());
     396          40 :             B2DPolyPolygon aRetval;
     397             : 
     398          80 :             for(sal_uInt32 a(0L); a < nPolygonCount; a++)
     399             :             {
     400          40 :                 const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
     401             : 
     402          40 :                 aRetval.append(expandToCurve(aCandidate));
     403          40 :             }
     404             : 
     405          40 :             return aRetval;
     406             :         }
     407             : 
     408         126 :         B2DPolyPolygon growInNormalDirection(const B2DPolyPolygon& rCandidate, double fValue)
     409             :         {
     410         126 :             if(0.0 != fValue)
     411             :             {
     412         126 :                 B2DPolyPolygon aRetval;
     413             : 
     414         252 :                 for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
     415             :                 {
     416         126 :                     aRetval.append(growInNormalDirection(rCandidate.getB2DPolygon(a), fValue));
     417             :                 }
     418             : 
     419         126 :                 return aRetval;
     420             :             }
     421             :             else
     422             :             {
     423           0 :                 return rCandidate;
     424             :             }
     425             :         }
     426             : 
     427           0 :         void correctGrowShrinkPolygonPair(SAL_UNUSED_PARAMETER B2DPolyPolygon& /*rOriginal*/, SAL_UNUSED_PARAMETER B2DPolyPolygon& /*rGrown*/)
     428             :         {
     429             :             //TODO!
     430           0 :         }
     431             : 
     432           0 :         B2DPolyPolygon reSegmentPolyPolygon(const B2DPolyPolygon& rCandidate, sal_uInt32 nSegments)
     433             :         {
     434           0 :             B2DPolyPolygon aRetval;
     435             : 
     436           0 :             for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
     437             :             {
     438           0 :                 aRetval.append(reSegmentPolygon(rCandidate.getB2DPolygon(a), nSegments));
     439             :             }
     440             : 
     441           0 :             return aRetval;
     442             :         }
     443             : 
     444           0 :         B2DPolyPolygon interpolate(const B2DPolyPolygon& rOld1, const B2DPolyPolygon& rOld2, double t)
     445             :         {
     446             :             OSL_ENSURE(rOld1.count() == rOld2.count(), "B2DPolyPolygon interpolate: Different geometry (!)");
     447           0 :             B2DPolyPolygon aRetval;
     448             : 
     449           0 :             for(sal_uInt32 a(0L); a < rOld1.count(); a++)
     450             :             {
     451           0 :                 aRetval.append(interpolate(rOld1.getB2DPolygon(a), rOld2.getB2DPolygon(a), t));
     452             :             }
     453             : 
     454           0 :             return aRetval;
     455             :         }
     456             : 
     457       11674 :         bool isRectangle( const B2DPolyPolygon& rPoly )
     458             :         {
     459             :             // exclude some cheap cases first
     460       11674 :             if( rPoly.count() != 1 )
     461           6 :                 return false;
     462             : 
     463       11668 :             return isRectangle( rPoly.getB2DPolygon(0) );
     464             :         }
     465             : 
     466             :         // #i76891#
     467         861 :         B2DPolyPolygon simplifyCurveSegments(const B2DPolyPolygon& rCandidate)
     468             :         {
     469         861 :             if(rCandidate.areControlPointsUsed())
     470             :             {
     471         517 :                 B2DPolyPolygon aRetval;
     472             : 
     473        2382 :                 for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
     474             :                 {
     475        1865 :                     aRetval.append(simplifyCurveSegments(rCandidate.getB2DPolygon(a)));
     476             :                 }
     477             : 
     478         517 :                 return aRetval;
     479             :             }
     480             :             else
     481             :             {
     482         344 :                 return rCandidate;
     483             :             }
     484             :         }
     485             : 
     486           0 :         B2DPolyPolygon snapPointsOfHorizontalOrVerticalEdges(const B2DPolyPolygon& rCandidate)
     487             :         {
     488           0 :             B2DPolyPolygon aRetval;
     489             : 
     490           0 :             for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
     491             :             {
     492           0 :                 aRetval.append(snapPointsOfHorizontalOrVerticalEdges(rCandidate.getB2DPolygon(a)));
     493             :             }
     494             : 
     495           0 :             return aRetval;
     496             :         }
     497             : 
     498           0 :         bool containsOnlyHorizontalAndVerticalEdges(const B2DPolyPolygon& rCandidate)
     499             :         {
     500           0 :             if(rCandidate.areControlPointsUsed())
     501             :             {
     502           0 :                 return false;
     503             :             }
     504             : 
     505           0 :             for(sal_uInt32 a(0); a < rCandidate.count(); a++)
     506             :             {
     507           0 :                 if(!containsOnlyHorizontalAndVerticalEdges(rCandidate.getB2DPolygon(a)))
     508             :                 {
     509           0 :                     return false;
     510             :                 }
     511             :             }
     512             : 
     513           0 :             return true;
     514             :         }
     515             : 
     516           0 :         B2DPolyPolygon createSevenSegmentPolyPolygon(sal_Char nNumber, bool bLitSegments)
     517             :         {
     518             :             // config here
     519             :             // {
     520           0 :             const double fTotalSize=1.0;
     521           0 :             const double fPosMiddleSegment=0.6;
     522           0 :             const double fSegmentEndChopHoriz=0.08;
     523           0 :             const double fSegmentEndChopVert =0.04;
     524             :             // }
     525             :             // config here
     526             : 
     527           0 :             const double fLeft=0.0;
     528           0 :             const double fRight=fTotalSize;
     529           0 :             const double fTop=0.0;
     530           0 :             const double fMiddle=fPosMiddleSegment;
     531           0 :             const double fBottom=fTotalSize;
     532             : 
     533             :             // from 0 to 5: pair of segment corner coordinates
     534             : 
     535             :             // segment corner indices are these:
     536             : 
     537             :             //   0 - 1
     538             :             //   |   |
     539             :             //   2 - 3
     540             :             //   |   |
     541             :             //   4 - 5
     542             : 
     543             :             static const double corners[] =
     544             :             {
     545             :                 fLeft,  fTop,
     546             :                 fRight, fTop,
     547             :                 fLeft,  fMiddle,
     548             :                 fRight, fMiddle,
     549             :                 fLeft,  fBottom,
     550             :                 fRight, fBottom
     551             :             };
     552             : 
     553             :             // from 0 to 9: which segments are 'lit' for this number?
     554             : 
     555             :             // array denotes graph edges to traverse, with -1 means
     556             :             // stop (the vertices are the corner indices from above):
     557             :             //     0
     558             :             //     -
     559             :             // 1 |   | 2
     560             :             //     - 3
     561             :             // 4 |   | 5
     562             :             //     -
     563             :             //     6
     564             : 
     565             :             static const int numbers[] =
     566             :             {
     567             :                 1, 1, 1, 0, 1, 1, 1, // 0
     568             :                 0, 0, 1, 0, 0, 1, 0, // 1
     569             :                 1, 0, 1, 1, 1, 0, 1, // 2
     570             :                 1, 0, 1, 1, 0, 1, 1, // 3
     571             :                 0, 1, 1, 1, 0, 1, 0, // 4
     572             :                 1, 1, 0, 1, 0, 1, 1, // 5
     573             :                 1, 1, 0, 1, 1, 1, 1, // 6
     574             :                 1, 0, 1, 0, 0, 1, 0, // 1
     575             :                 1, 1, 1, 1, 1, 1, 1, // 8
     576             :                 1, 1, 1, 1, 0, 1, 1, // 9
     577             :                 0, 0, 0, 1, 0, 0, 0, // '-'
     578             :                 1, 1, 0, 1, 1, 0, 1, // 'E'
     579             :             };
     580             : 
     581             :             // maps segment index to two corner ids:
     582             :             static const int index2corner[] =
     583             :             {
     584             :                 0, 2,  // 0
     585             :                 0, 4,  // 1
     586             :                 2, 6,  // 2
     587             :                 4, 6,  // 3
     588             :                 4, 8,  // 4
     589             :                 6, 10, // 5
     590             :                 8, 10, // 6
     591             :             };
     592             : 
     593           0 :             B2DPolyPolygon aRes;
     594           0 :             if( nNumber == '-' )
     595             :             {
     596           0 :                 nNumber = 10;
     597             :             }
     598           0 :             else if( nNumber == 'E' )
     599             :             {
     600           0 :                 nNumber = 11;
     601             :             }
     602           0 :             else if( nNumber == '.' )
     603             :             {
     604           0 :                 if( bLitSegments )
     605             :                     aRes.append(createPolygonFromCircle(B2DPoint(fTotalSize/2, fTotalSize),
     606           0 :                                                         fSegmentEndChopHoriz));
     607           0 :                 return aRes;
     608             :             }
     609             :             else
     610             :             {
     611           0 :                 nNumber=clamp<sal_uInt32>(nNumber,'0','9') - '0';
     612             :             }
     613             : 
     614           0 :             B2DPolygon aCurrSegment;
     615           0 :             const size_t sliceSize=SAL_N_ELEMENTS(numbers)/12;
     616           0 :             const int* pCurrSegment=numbers + nNumber*sliceSize;
     617           0 :             for( size_t i=0; i<sliceSize; i++, pCurrSegment++)
     618             :             {
     619           0 :                 if( !(*pCurrSegment ^ int(bLitSegments)) )
     620             :                 {
     621           0 :                     const size_t j=2*i;
     622           0 :                     aCurrSegment.clear();
     623           0 :                     B2DPoint start(corners[index2corner[j]],
     624           0 :                                    corners[index2corner[j]+1]  );
     625           0 :                     B2DPoint end  (corners[index2corner[j+1]],
     626           0 :                                    corners[index2corner[j+1]+1]);
     627             : 
     628           0 :                     if( start.getX() == end.getX() )
     629             :                     {
     630           0 :                         start.setY(start.getY()+fSegmentEndChopVert);
     631           0 :                         end.setY(end.getY()-fSegmentEndChopVert);
     632             :                     }
     633             :                     else
     634             :                     {
     635           0 :                         start.setX(start.getX()+fSegmentEndChopHoriz);
     636           0 :                         end.setX(end.getX()-fSegmentEndChopHoriz);
     637             :                     }
     638             : 
     639           0 :                     aCurrSegment.append(start);
     640           0 :                     aCurrSegment.append(end);
     641             :                 }
     642           0 :                 aRes.append(aCurrSegment);
     643             :             }
     644             : 
     645           0 :             return aRes;
     646             :         }
     647             : 
     648             :         // converters for com::sun::star::drawing::PointSequence
     649             : 
     650          22 :         B2DPolyPolygon UnoPointSequenceSequenceToB2DPolyPolygon(
     651             :             const com::sun::star::drawing::PointSequenceSequence& rPointSequenceSequenceSource,
     652             :             bool bCheckClosed)
     653             :         {
     654          22 :             B2DPolyPolygon aRetval;
     655          22 :             const com::sun::star::drawing::PointSequence* pPointSequence = rPointSequenceSequenceSource.getConstArray();
     656          22 :             const com::sun::star::drawing::PointSequence* pPointSeqEnd = pPointSequence + rPointSequenceSequenceSource.getLength();
     657             : 
     658          24 :             for(;pPointSequence != pPointSeqEnd; pPointSequence++)
     659             :             {
     660           2 :                 const B2DPolygon aNewPolygon = UnoPointSequenceToB2DPolygon(*pPointSequence, bCheckClosed);
     661           2 :                 aRetval.append(aNewPolygon);
     662           2 :             }
     663             : 
     664          22 :             return aRetval;
     665             :         }
     666             : 
     667         860 :         void B2DPolyPolygonToUnoPointSequenceSequence(
     668             :             const B2DPolyPolygon& rPolyPolygon,
     669             :             com::sun::star::drawing::PointSequenceSequence& rPointSequenceSequenceRetval)
     670             :         {
     671         860 :             const sal_uInt32 nCount(rPolyPolygon.count());
     672             : 
     673         860 :             if(nCount)
     674             :             {
     675         860 :                 rPointSequenceSequenceRetval.realloc(nCount);
     676         860 :                 com::sun::star::drawing::PointSequence* pPointSequence = rPointSequenceSequenceRetval.getArray();
     677             : 
     678        1720 :                 for(sal_uInt32 a(0); a < nCount; a++)
     679             :                 {
     680         860 :                     const B2DPolygon aPolygon(rPolyPolygon.getB2DPolygon(a));
     681             : 
     682         860 :                     B2DPolygonToUnoPointSequence(aPolygon, *pPointSequence);
     683         860 :                     pPointSequence++;
     684         860 :                 }
     685             :             }
     686             :             else
     687             :             {
     688           0 :                 rPointSequenceSequenceRetval.realloc(0);
     689             :             }
     690         860 :         }
     691             : 
     692             :         // converters for com::sun::star::drawing::PolyPolygonBezierCoords (curved polygons)
     693             : 
     694          26 :         B2DPolyPolygon UnoPolyPolygonBezierCoordsToB2DPolyPolygon(
     695             :             const com::sun::star::drawing::PolyPolygonBezierCoords& rPolyPolygonBezierCoordsSource,
     696             :             bool bCheckClosed)
     697             :         {
     698          26 :             B2DPolyPolygon aRetval;
     699          26 :             const sal_uInt32 nSequenceCount((sal_uInt32)rPolyPolygonBezierCoordsSource.Coordinates.getLength());
     700             : 
     701          26 :             if(nSequenceCount)
     702             :             {
     703             :                 OSL_ENSURE(nSequenceCount == (sal_uInt32)rPolyPolygonBezierCoordsSource.Flags.getLength(),
     704             :                     "UnoPolyPolygonBezierCoordsToB2DPolyPolygon: unequal number of Points and Flags (!)");
     705          26 :                 const com::sun::star::drawing::PointSequence* pPointSequence = rPolyPolygonBezierCoordsSource.Coordinates.getConstArray();
     706          26 :                 const com::sun::star::drawing::FlagSequence* pFlagSequence = rPolyPolygonBezierCoordsSource.Flags.getConstArray();
     707             : 
     708          52 :                 for(sal_uInt32 a(0); a < nSequenceCount; a++)
     709             :                 {
     710             :                     const B2DPolygon aNewPolygon(UnoPolygonBezierCoordsToB2DPolygon(
     711             :                         *pPointSequence,
     712             :                         *pFlagSequence,
     713          26 :                         bCheckClosed));
     714             : 
     715          26 :                     pPointSequence++;
     716          26 :                     pFlagSequence++;
     717          26 :                     aRetval.append(aNewPolygon);
     718          26 :                 }
     719             :             }
     720             : 
     721          26 :             return aRetval;
     722             :         }
     723             : 
     724         704 :         void B2DPolyPolygonToUnoPolyPolygonBezierCoords(
     725             :             const B2DPolyPolygon& rPolyPolygon,
     726             :             com::sun::star::drawing::PolyPolygonBezierCoords& rPolyPolygonBezierCoordsRetval)
     727             :         {
     728         704 :             const sal_uInt32 nCount(rPolyPolygon.count());
     729             : 
     730         704 :             if(nCount)
     731             :             {
     732             :                 // prepare return value memory
     733         704 :                 rPolyPolygonBezierCoordsRetval.Coordinates.realloc((sal_Int32)nCount);
     734         704 :                 rPolyPolygonBezierCoordsRetval.Flags.realloc((sal_Int32)nCount);
     735             : 
     736             :                 // get pointers to arrays
     737         704 :                 com::sun::star::drawing::PointSequence* pPointSequence = rPolyPolygonBezierCoordsRetval.Coordinates.getArray();
     738         704 :                 com::sun::star::drawing::FlagSequence*  pFlagSequence = rPolyPolygonBezierCoordsRetval.Flags.getArray();
     739             : 
     740        1648 :                 for(sal_uInt32 a(0); a < nCount; a++)
     741             :                 {
     742         944 :                     const B2DPolygon aSource(rPolyPolygon.getB2DPolygon(a));
     743             : 
     744             :                     B2DPolygonToUnoPolygonBezierCoords(
     745             :                         aSource,
     746             :                         *pPointSequence,
     747         944 :                         *pFlagSequence);
     748         944 :                     pPointSequence++;
     749         944 :                     pFlagSequence++;
     750         944 :                 }
     751             :             }
     752             :             else
     753             :             {
     754           0 :                 rPolyPolygonBezierCoordsRetval.Coordinates.realloc(0);
     755           0 :                 rPolyPolygonBezierCoordsRetval.Flags.realloc(0);
     756             :             }
     757         704 :         }
     758             : 
     759             :     } // end of namespace tools
     760             : } // end of namespace basegfx
     761             : 
     762             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10