LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/basegfx/source/polygon - b3dpolygon.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 435 767 56.7 %
Date: 2013-07-09 Functions: 101 134 75.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <osl/diagnose.h>
      21             : #include <basegfx/polygon/b3dpolygon.hxx>
      22             : #include <basegfx/point/b3dpoint.hxx>
      23             : #include <basegfx/matrix/b3dhommatrix.hxx>
      24             : #include <rtl/instance.hxx>
      25             : #include <basegfx/point/b2dpoint.hxx>
      26             : #include <basegfx/color/bcolor.hxx>
      27             : #include <basegfx/matrix/b2dhommatrix.hxx>
      28             : #include <vector>
      29             : #include <algorithm>
      30             : 
      31             : //////////////////////////////////////////////////////////////////////////////
      32             : 
      33      260270 : class CoordinateData3D
      34             : {
      35             :     basegfx::B3DPoint                               maPoint;
      36             : 
      37             : public:
      38           0 :     CoordinateData3D()
      39           0 :     :   maPoint()
      40             :     {
      41           0 :     }
      42             : 
      43       33482 :     explicit CoordinateData3D(const basegfx::B3DPoint& rData)
      44       33482 :     :   maPoint(rData)
      45             :     {
      46       33482 :     }
      47             : 
      48      148056 :     const basegfx::B3DPoint& getCoordinate() const
      49             :     {
      50      148056 :         return maPoint;
      51             :     }
      52             : 
      53           0 :     void setCoordinate(const basegfx::B3DPoint& rValue)
      54             :     {
      55           0 :         if(rValue != maPoint)
      56           0 :             maPoint = rValue;
      57           0 :     }
      58             : 
      59       42080 :     bool operator==(const CoordinateData3D& rData) const
      60             :     {
      61       42080 :         return (maPoint == rData.getCoordinate());
      62             :     }
      63             : 
      64       16870 :     void transform(const basegfx::B3DHomMatrix& rMatrix)
      65             :     {
      66       16870 :         maPoint *= rMatrix;
      67       16870 :     }
      68             : };
      69             : 
      70             : //////////////////////////////////////////////////////////////////////////////
      71             : 
      72             : class CoordinateDataArray3D
      73             : {
      74             :     typedef ::std::vector< CoordinateData3D > CoordinateData3DVector;
      75             : 
      76             :     CoordinateData3DVector                          maVector;
      77             : 
      78             : public:
      79           1 :     explicit CoordinateDataArray3D(sal_uInt32 nCount)
      80           1 :     :   maVector(nCount)
      81             :     {
      82           1 :     }
      83             : 
      84       15314 :     explicit CoordinateDataArray3D(const CoordinateDataArray3D& rOriginal)
      85       15314 :     :   maVector(rOriginal.maVector)
      86             :     {
      87       15314 :     }
      88             : 
      89           0 :     CoordinateDataArray3D(const CoordinateDataArray3D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
      90           0 :     :   maVector(rOriginal.maVector.begin() + nIndex, rOriginal.maVector.begin() + (nIndex + nCount))
      91             :     {
      92           0 :     }
      93             : 
      94       15315 :     ~CoordinateDataArray3D()
      95       15315 :     {
      96       15315 :     }
      97             : 
      98         628 :     ::basegfx::B3DVector getNormal() const
      99             :     {
     100         628 :         ::basegfx::B3DVector aRetval;
     101         628 :         const sal_uInt32 nPointCount(maVector.size());
     102             : 
     103         628 :         if(nPointCount > 2)
     104             :         {
     105         628 :             sal_uInt32 nISmallest(0);
     106         628 :             sal_uInt32 a(0);
     107         628 :             const basegfx::B3DPoint* pSmallest(&maVector[0].getCoordinate());
     108         628 :             const basegfx::B3DPoint* pNext(0);
     109         628 :             const basegfx::B3DPoint* pPrev(0);
     110             : 
     111             :             // To guarantee a correctly oriented point, choose an outmost one
     112             :             // which then cannot be concave
     113        2512 :             for(a = 1; a < nPointCount; a++)
     114             :             {
     115        1884 :                 const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
     116             : 
     117        3768 :                 if((rCandidate.getX() < pSmallest->getX())
     118        1419 :                     || (rCandidate.getX() == pSmallest->getX() && rCandidate.getY() < pSmallest->getY())
     119        3285 :                     || (rCandidate.getX() == pSmallest->getX() && rCandidate.getY() == pSmallest->getY() && rCandidate.getZ() < pSmallest->getZ()))
     120             :                 {
     121         602 :                     nISmallest = a;
     122         602 :                     pSmallest = &rCandidate;
     123             :                 }
     124             :             }
     125             : 
     126             :             // look for a next point different from minimal one
     127         628 :             for(a = (nISmallest + 1) % nPointCount; a != nISmallest; a = (a + 1) % nPointCount)
     128             :             {
     129         628 :                 const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
     130             : 
     131         628 :                 if(!rCandidate.equal(*pSmallest))
     132             :                 {
     133         628 :                     pNext = &rCandidate;
     134         628 :                     break;
     135             :                 }
     136             :             }
     137             : 
     138             :             // look for a previous point different from minimal one
     139         628 :             for(a = (nISmallest + nPointCount - 1) % nPointCount; a != nISmallest; a = (a + nPointCount - 1) % nPointCount)
     140             :             {
     141         628 :                 const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
     142             : 
     143         628 :                 if(!rCandidate.equal(*pSmallest))
     144             :                 {
     145         628 :                     pPrev = &rCandidate;
     146         628 :                     break;
     147             :                 }
     148             :             }
     149             : 
     150             :             // we always have a minimal point. If we also have a different next and previous,
     151             :             // we can calculate the normal
     152         628 :             if(pNext && pPrev)
     153             :             {
     154         628 :                 const basegfx::B3DVector aPrev(*pPrev - *pSmallest);
     155        1256 :                 const basegfx::B3DVector aNext(*pNext - *pSmallest);
     156             : 
     157         628 :                 aRetval = cross(aPrev, aNext);
     158        1256 :                 aRetval.normalize();
     159             :             }
     160             :         }
     161             : 
     162         628 :         return aRetval;
     163             :     }
     164             : 
     165      132293 :     sal_uInt32 count() const
     166             :     {
     167      132293 :         return maVector.size();
     168             :     }
     169             : 
     170       10520 :     bool operator==(const CoordinateDataArray3D& rCandidate) const
     171             :     {
     172       10520 :         return (maVector == rCandidate.maVector);
     173             :     }
     174             : 
     175      102208 :     const basegfx::B3DPoint& getCoordinate(sal_uInt32 nIndex) const
     176             :     {
     177      102208 :         return maVector[nIndex].getCoordinate();
     178             :     }
     179             : 
     180           0 :     void setCoordinate(sal_uInt32 nIndex, const basegfx::B3DPoint& rValue)
     181             :     {
     182           0 :         maVector[nIndex].setCoordinate(rValue);
     183           0 :     }
     184             : 
     185       33482 :     void insert(sal_uInt32 nIndex, const CoordinateData3D& rValue, sal_uInt32 nCount)
     186             :     {
     187       33482 :         if(nCount)
     188             :         {
     189             :             // add nCount copies of rValue
     190       33482 :             CoordinateData3DVector::iterator aIndex(maVector.begin());
     191       33482 :             aIndex += nIndex;
     192       33482 :             maVector.insert(aIndex, nCount, rValue);
     193             :         }
     194       33482 :     }
     195             : 
     196           0 :     void insert(sal_uInt32 nIndex, const CoordinateDataArray3D& rSource)
     197             :     {
     198           0 :         const sal_uInt32 nCount(rSource.maVector.size());
     199             : 
     200           0 :         if(nCount)
     201             :         {
     202             :             // insert data
     203           0 :             CoordinateData3DVector::iterator aIndex(maVector.begin());
     204           0 :             aIndex += nIndex;
     205           0 :             CoordinateData3DVector::const_iterator aStart(rSource.maVector.begin());
     206           0 :             CoordinateData3DVector::const_iterator aEnd(rSource.maVector.end());
     207           0 :             maVector.insert(aIndex, aStart, aEnd);
     208             :         }
     209           0 :     }
     210             : 
     211         842 :     void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
     212             :     {
     213         842 :         if(nCount)
     214             :         {
     215             :             // remove point data
     216         842 :             CoordinateData3DVector::iterator aStart(maVector.begin());
     217         842 :             aStart += nIndex;
     218         842 :             const CoordinateData3DVector::iterator aEnd(aStart + nCount);
     219         842 :             maVector.erase(aStart, aEnd);
     220             :         }
     221         842 :     }
     222             : 
     223        5216 :     void flip()
     224             :     {
     225        5216 :         if(maVector.size() > 1)
     226             :         {
     227        5216 :             const sal_uInt32 nHalfSize(maVector.size() >> 1L);
     228        5216 :             CoordinateData3DVector::iterator aStart(maVector.begin());
     229        5216 :             CoordinateData3DVector::iterator aEnd(maVector.end() - 1L);
     230             : 
     231       15648 :             for(sal_uInt32 a(0); a < nHalfSize; a++)
     232             :             {
     233       10432 :                 ::std::swap(*aStart, *aEnd);
     234       10432 :                 ++aStart;
     235       10432 :                 --aEnd;
     236             :             }
     237             :         }
     238        5216 :     }
     239             : 
     240        5217 :     void transform(const ::basegfx::B3DHomMatrix& rMatrix)
     241             :     {
     242        5217 :         CoordinateData3DVector::iterator aStart(maVector.begin());
     243        5217 :         CoordinateData3DVector::iterator aEnd(maVector.end());
     244             : 
     245       22087 :         for(; aStart != aEnd; ++aStart)
     246             :         {
     247       16870 :             aStart->transform(rMatrix);
     248             :         }
     249        5217 :     }
     250             : };
     251             : 
     252             : //////////////////////////////////////////////////////////////////////////////
     253             : 
     254             : class BColorArray
     255             : {
     256             :     typedef ::std::vector< ::basegfx::BColor > BColorDataVector;
     257             : 
     258             :     BColorDataVector                                    maVector;
     259             :     sal_uInt32                                          mnUsedEntries;
     260             : 
     261             : public:
     262          66 :     explicit BColorArray(sal_uInt32 nCount)
     263             :     :   maVector(nCount),
     264          66 :         mnUsedEntries(0L)
     265             :     {
     266          66 :     }
     267             : 
     268           0 :     explicit BColorArray(const BColorArray& rOriginal)
     269             :     :   maVector(rOriginal.maVector),
     270           0 :         mnUsedEntries(rOriginal.mnUsedEntries)
     271             :     {
     272           0 :     }
     273             : 
     274           0 :     BColorArray(const BColorArray& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
     275             :     :   maVector(),
     276           0 :         mnUsedEntries(0L)
     277             :     {
     278           0 :         BColorDataVector::const_iterator aStart(rOriginal.maVector.begin());
     279           0 :         aStart += nIndex;
     280           0 :         BColorDataVector::const_iterator aEnd(aStart);
     281             :         assert(nCount <= rOriginal.maVector.size());
     282           0 :         aEnd += nCount;
     283           0 :         maVector.reserve(nCount);
     284             : 
     285           0 :         for(; aStart != aEnd; ++aStart)
     286             :         {
     287           0 :             if(!aStart->equalZero())
     288           0 :                 mnUsedEntries++;
     289             : 
     290           0 :             maVector.push_back(*aStart);
     291             :         }
     292           0 :     }
     293             : 
     294          66 :     ~BColorArray()
     295          66 :     {
     296          66 :     }
     297             : 
     298             :     sal_uInt32 count() const
     299             :     {
     300             :         return maVector.size();
     301             :     }
     302             : 
     303           0 :     bool operator==(const BColorArray& rCandidate) const
     304             :     {
     305           0 :         return (maVector == rCandidate.maVector);
     306             :     }
     307             : 
     308         528 :     bool isUsed() const
     309             :     {
     310         528 :         return (0L != mnUsedEntries);
     311             :     }
     312             : 
     313         726 :     const ::basegfx::BColor& getBColor(sal_uInt32 nIndex) const
     314             :     {
     315         726 :         return maVector[nIndex];
     316             :     }
     317             : 
     318         264 :     void setBColor(sal_uInt32 nIndex, const ::basegfx::BColor& rValue)
     319             :     {
     320         264 :         bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
     321         264 :         bool bIsUsed(!rValue.equalZero());
     322             : 
     323         264 :         if(bWasUsed)
     324             :         {
     325           0 :             if(bIsUsed)
     326             :             {
     327           0 :                 maVector[nIndex] = rValue;
     328             :             }
     329             :             else
     330             :             {
     331           0 :                 maVector[nIndex] = ::basegfx::BColor::getEmptyBColor();
     332           0 :                 mnUsedEntries--;
     333             :             }
     334             :         }
     335             :         else
     336             :         {
     337         264 :             if(bIsUsed)
     338             :             {
     339         264 :                 maVector[nIndex] = rValue;
     340         264 :                 mnUsedEntries++;
     341             :             }
     342             :         }
     343         264 :     }
     344             : 
     345           0 :     void insert(sal_uInt32 nIndex, const ::basegfx::BColor& rValue, sal_uInt32 nCount)
     346             :     {
     347           0 :         if(nCount)
     348             :         {
     349             :             // add nCount copies of rValue
     350           0 :             BColorDataVector::iterator aIndex(maVector.begin());
     351           0 :             aIndex += nIndex;
     352           0 :             maVector.insert(aIndex, nCount, rValue);
     353             : 
     354           0 :             if(!rValue.equalZero())
     355           0 :                 mnUsedEntries += nCount;
     356             :         }
     357           0 :     }
     358             : 
     359           0 :     void insert(sal_uInt32 nIndex, const BColorArray& rSource)
     360             :     {
     361           0 :         const sal_uInt32 nCount(rSource.maVector.size());
     362             : 
     363           0 :         if(nCount)
     364             :         {
     365             :             // insert data
     366           0 :             BColorDataVector::iterator aIndex(maVector.begin());
     367           0 :             aIndex += nIndex;
     368           0 :             BColorDataVector::const_iterator aStart(rSource.maVector.begin());
     369           0 :             BColorDataVector::const_iterator aEnd(rSource.maVector.end());
     370           0 :             maVector.insert(aIndex, aStart, aEnd);
     371             : 
     372           0 :             for(; aStart != aEnd; ++aStart)
     373             :             {
     374           0 :                 if(!aStart->equalZero())
     375           0 :                     mnUsedEntries++;
     376             :             }
     377             :         }
     378           0 :     }
     379             : 
     380           0 :     void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
     381             :     {
     382           0 :         if(nCount)
     383             :         {
     384           0 :             const BColorDataVector::iterator aDeleteStart(maVector.begin() + nIndex);
     385           0 :             const BColorDataVector::iterator aDeleteEnd(aDeleteStart + nCount);
     386           0 :             BColorDataVector::const_iterator aStart(aDeleteStart);
     387             : 
     388           0 :             for(; mnUsedEntries && aStart != aDeleteEnd; ++aStart)
     389             :             {
     390           0 :                 if(!aStart->equalZero())
     391           0 :                     mnUsedEntries--;
     392             :             }
     393             : 
     394             :             // remove point data
     395           0 :             maVector.erase(aDeleteStart, aDeleteEnd);
     396             :         }
     397           0 :     }
     398             : 
     399           0 :     void flip()
     400             :     {
     401           0 :         if(maVector.size() > 1)
     402             :         {
     403           0 :             const sal_uInt32 nHalfSize(maVector.size() >> 1L);
     404           0 :             BColorDataVector::iterator aStart(maVector.begin());
     405           0 :             BColorDataVector::iterator aEnd(maVector.end() - 1L);
     406             : 
     407           0 :             for(sal_uInt32 a(0); a < nHalfSize; a++)
     408             :             {
     409           0 :                 ::std::swap(*aStart, *aEnd);
     410           0 :                 ++aStart;
     411           0 :                 --aEnd;
     412             :             }
     413             :         }
     414           0 :     }
     415             : };
     416             : 
     417             : //////////////////////////////////////////////////////////////////////////////
     418             : 
     419             : class NormalsArray3D
     420             : {
     421             :     typedef ::std::vector< ::basegfx::B3DVector > NormalsData3DVector;
     422             : 
     423             :     NormalsData3DVector                                 maVector;
     424             :     sal_uInt32                                          mnUsedEntries;
     425             : 
     426             : public:
     427        5384 :     explicit NormalsArray3D(sal_uInt32 nCount)
     428             :     :   maVector(nCount),
     429        5384 :         mnUsedEntries(0L)
     430             :     {
     431        5384 :     }
     432             : 
     433         529 :     explicit NormalsArray3D(const NormalsArray3D& rOriginal)
     434             :     :   maVector(rOriginal.maVector),
     435         529 :         mnUsedEntries(rOriginal.mnUsedEntries)
     436             :     {
     437         529 :     }
     438             : 
     439           0 :     NormalsArray3D(const NormalsArray3D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
     440             :     :   maVector(),
     441           0 :         mnUsedEntries(0L)
     442             :     {
     443           0 :         NormalsData3DVector::const_iterator aStart(rOriginal.maVector.begin());
     444           0 :         aStart += nIndex;
     445           0 :         NormalsData3DVector::const_iterator aEnd(aStart);
     446           0 :         aEnd += nCount;
     447           0 :         maVector.reserve(nCount);
     448             : 
     449           0 :         for(; aStart != aEnd; ++aStart)
     450             :         {
     451           0 :             if(!aStart->equalZero())
     452           0 :                 mnUsedEntries++;
     453             : 
     454           0 :             maVector.push_back(*aStart);
     455             :         }
     456           0 :     }
     457             : 
     458        5913 :     ~NormalsArray3D()
     459        5913 :     {
     460        5913 :     }
     461             : 
     462             :     sal_uInt32 count() const
     463             :     {
     464             :         return maVector.size();
     465             :     }
     466             : 
     467        5118 :     bool operator==(const NormalsArray3D& rCandidate) const
     468             :     {
     469        5118 :         return (maVector == rCandidate.maVector);
     470             :     }
     471             : 
     472       17649 :     bool isUsed() const
     473             :     {
     474       17649 :         return (0L != mnUsedEntries);
     475             :     }
     476             : 
     477       17376 :     const ::basegfx::B3DVector& getNormal(sal_uInt32 nIndex) const
     478             :     {
     479       17376 :         return maVector[nIndex];
     480             :     }
     481             : 
     482       16536 :     void setNormal(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue)
     483             :     {
     484       16536 :         bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
     485       16536 :         bool bIsUsed(!rValue.equalZero());
     486             : 
     487       16536 :         if(bWasUsed)
     488             :         {
     489         192 :             if(bIsUsed)
     490             :             {
     491         192 :                 maVector[nIndex] = rValue;
     492             :             }
     493             :             else
     494             :             {
     495           0 :                 maVector[nIndex] = ::basegfx::B3DVector::getEmptyVector();
     496           0 :                 mnUsedEntries--;
     497             :             }
     498             :         }
     499             :         else
     500             :         {
     501       16344 :             if(bIsUsed)
     502             :             {
     503       16344 :                 maVector[nIndex] = rValue;
     504       16344 :                 mnUsedEntries++;
     505             :             }
     506             :         }
     507       16536 :     }
     508             : 
     509           0 :     void insert(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue, sal_uInt32 nCount)
     510             :     {
     511           0 :         if(nCount)
     512             :         {
     513             :             // add nCount copies of rValue
     514           0 :             NormalsData3DVector::iterator aIndex(maVector.begin());
     515           0 :             aIndex += nIndex;
     516           0 :             maVector.insert(aIndex, nCount, rValue);
     517             : 
     518           0 :             if(!rValue.equalZero())
     519           0 :                 mnUsedEntries += nCount;
     520             :         }
     521           0 :     }
     522             : 
     523           0 :     void insert(sal_uInt32 nIndex, const NormalsArray3D& rSource)
     524             :     {
     525           0 :         const sal_uInt32 nCount(rSource.maVector.size());
     526             : 
     527           0 :         if(nCount)
     528             :         {
     529             :             // insert data
     530           0 :             NormalsData3DVector::iterator aIndex(maVector.begin());
     531           0 :             aIndex += nIndex;
     532           0 :             NormalsData3DVector::const_iterator aStart(rSource.maVector.begin());
     533           0 :             NormalsData3DVector::const_iterator aEnd(rSource.maVector.end());
     534           0 :             maVector.insert(aIndex, aStart, aEnd);
     535             : 
     536           0 :             for(; aStart != aEnd; ++aStart)
     537             :             {
     538           0 :                 if(!aStart->equalZero())
     539           0 :                     mnUsedEntries++;
     540             :             }
     541             :         }
     542           0 :     }
     543             : 
     544           0 :     void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
     545             :     {
     546           0 :         if(nCount)
     547             :         {
     548           0 :             const NormalsData3DVector::iterator aDeleteStart(maVector.begin() + nIndex);
     549           0 :             const NormalsData3DVector::iterator aDeleteEnd(aDeleteStart + nCount);
     550           0 :             NormalsData3DVector::const_iterator aStart(aDeleteStart);
     551             : 
     552           0 :             for(; mnUsedEntries && aStart != aDeleteEnd; ++aStart)
     553             :             {
     554           0 :                 if(!aStart->equalZero())
     555           0 :                     mnUsedEntries--;
     556             :             }
     557             : 
     558             :             // remove point data
     559           0 :             maVector.erase(aDeleteStart, aDeleteEnd);
     560             :         }
     561           0 :     }
     562             : 
     563        5216 :     void flip()
     564             :     {
     565        5216 :         if(maVector.size() > 1)
     566             :         {
     567        5216 :             const sal_uInt32 nHalfSize(maVector.size() >> 1L);
     568        5216 :             NormalsData3DVector::iterator aStart(maVector.begin());
     569        5216 :             NormalsData3DVector::iterator aEnd(maVector.end() - 1L);
     570             : 
     571       15648 :             for(sal_uInt32 a(0); a < nHalfSize; a++)
     572             :             {
     573       10432 :                 ::std::swap(*aStart, *aEnd);
     574       10432 :                 ++aStart;
     575       10432 :                 --aEnd;
     576             :             }
     577             :         }
     578        5216 :     }
     579             : 
     580          66 :     void transform(const basegfx::B3DHomMatrix& rMatrix)
     581             :     {
     582          66 :         const NormalsData3DVector::const_iterator aEnd(maVector.end());
     583             : 
     584         330 :         for(NormalsData3DVector::iterator aStart(maVector.begin()); aStart != aEnd; ++aStart)
     585             :         {
     586         264 :             (*aStart) *= rMatrix;
     587             :         }
     588          66 :     }
     589             : };
     590             : 
     591             : //////////////////////////////////////////////////////////////////////////////
     592             : 
     593             : class TextureCoordinate2D
     594             : {
     595             :     typedef ::std::vector< ::basegfx::B2DPoint > TextureData2DVector;
     596             : 
     597             :     TextureData2DVector                                 maVector;
     598             :     sal_uInt32                                          mnUsedEntries;
     599             : 
     600             : public:
     601        5336 :     explicit TextureCoordinate2D(sal_uInt32 nCount)
     602             :     :   maVector(nCount),
     603        5336 :         mnUsedEntries(0L)
     604             :     {
     605        5336 :     }
     606             : 
     607         454 :     explicit TextureCoordinate2D(const TextureCoordinate2D& rOriginal)
     608             :     :   maVector(rOriginal.maVector),
     609         454 :         mnUsedEntries(rOriginal.mnUsedEntries)
     610             :     {
     611         454 :     }
     612             : 
     613           0 :     TextureCoordinate2D(const TextureCoordinate2D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
     614             :     :   maVector(),
     615           0 :         mnUsedEntries(0L)
     616             :     {
     617           0 :         TextureData2DVector::const_iterator aStart(rOriginal.maVector.begin());
     618           0 :         aStart += nIndex;
     619           0 :         TextureData2DVector::const_iterator aEnd(aStart);
     620           0 :         aEnd += nCount;
     621           0 :         maVector.reserve(nCount);
     622             : 
     623           0 :         for(; aStart != aEnd; ++aStart)
     624             :         {
     625           0 :             if(!aStart->equalZero())
     626           0 :                 mnUsedEntries++;
     627             : 
     628           0 :             maVector.push_back(*aStart);
     629             :         }
     630           0 :     }
     631             : 
     632        5790 :     ~TextureCoordinate2D()
     633        5790 :     {
     634        5790 :     }
     635             : 
     636             :     sal_uInt32 count() const
     637             :     {
     638             :         return maVector.size();
     639             :     }
     640             : 
     641        5070 :     bool operator==(const TextureCoordinate2D& rCandidate) const
     642             :     {
     643        5070 :         return (maVector == rCandidate.maVector);
     644             :     }
     645             : 
     646       12214 :     bool isUsed() const
     647             :     {
     648       12214 :         return (0L != mnUsedEntries);
     649             :     }
     650             : 
     651       16328 :     const ::basegfx::B2DPoint& getTextureCoordinate(sal_uInt32 nIndex) const
     652             :     {
     653       16328 :         return maVector[nIndex];
     654             :     }
     655             : 
     656       16008 :     void setTextureCoordinate(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue)
     657             :     {
     658       16008 :         bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
     659       16008 :         bool bIsUsed(!rValue.equalZero());
     660             : 
     661       16008 :         if(bWasUsed)
     662             :         {
     663           0 :             if(bIsUsed)
     664             :             {
     665           0 :                 maVector[nIndex] = rValue;
     666             :             }
     667             :             else
     668             :             {
     669           0 :                 maVector[nIndex] = ::basegfx::B2DPoint::getEmptyPoint();
     670           0 :                 mnUsedEntries--;
     671             :             }
     672             :         }
     673             :         else
     674             :         {
     675       16008 :             if(bIsUsed)
     676             :             {
     677       16008 :                 maVector[nIndex] = rValue;
     678       16008 :                 mnUsedEntries++;
     679             :             }
     680             :         }
     681       16008 :     }
     682             : 
     683           0 :     void insert(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue, sal_uInt32 nCount)
     684             :     {
     685           0 :         if(nCount)
     686             :         {
     687             :             // add nCount copies of rValue
     688           0 :             TextureData2DVector::iterator aIndex(maVector.begin());
     689           0 :             aIndex += nIndex;
     690           0 :             maVector.insert(aIndex, nCount, rValue);
     691             : 
     692           0 :             if(!rValue.equalZero())
     693           0 :                 mnUsedEntries += nCount;
     694             :         }
     695           0 :     }
     696             : 
     697           0 :     void insert(sal_uInt32 nIndex, const TextureCoordinate2D& rSource)
     698             :     {
     699           0 :         const sal_uInt32 nCount(rSource.maVector.size());
     700             : 
     701           0 :         if(nCount)
     702             :         {
     703             :             // insert data
     704           0 :             TextureData2DVector::iterator aIndex(maVector.begin());
     705           0 :             aIndex += nIndex;
     706           0 :             TextureData2DVector::const_iterator aStart(rSource.maVector.begin());
     707           0 :             TextureData2DVector::const_iterator aEnd(rSource.maVector.end());
     708           0 :             maVector.insert(aIndex, aStart, aEnd);
     709             : 
     710           0 :             for(; aStart != aEnd; ++aStart)
     711             :             {
     712           0 :                 if(!aStart->equalZero())
     713           0 :                     mnUsedEntries++;
     714             :             }
     715             :         }
     716           0 :     }
     717             : 
     718           0 :     void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
     719             :     {
     720           0 :         if(nCount)
     721             :         {
     722           0 :             const TextureData2DVector::iterator aDeleteStart(maVector.begin() + nIndex);
     723           0 :             const TextureData2DVector::iterator aDeleteEnd(aDeleteStart + nCount);
     724           0 :             TextureData2DVector::const_iterator aStart(aDeleteStart);
     725             : 
     726           0 :             for(; mnUsedEntries && aStart != aDeleteEnd; ++aStart)
     727             :             {
     728           0 :                 if(!aStart->equalZero())
     729           0 :                     mnUsedEntries--;
     730             :             }
     731             : 
     732             :             // remove point data
     733           0 :             maVector.erase(aDeleteStart, aDeleteEnd);
     734             :         }
     735           0 :     }
     736             : 
     737        5192 :     void flip()
     738             :     {
     739        5192 :         if(maVector.size() > 1)
     740             :         {
     741        5192 :             const sal_uInt32 nHalfSize(maVector.size() >> 1L);
     742        5192 :             TextureData2DVector::iterator aStart(maVector.begin());
     743        5192 :             TextureData2DVector::iterator aEnd(maVector.end() - 1L);
     744             : 
     745       15576 :             for(sal_uInt32 a(0); a < nHalfSize; a++)
     746             :             {
     747       10384 :                 ::std::swap(*aStart, *aEnd);
     748       10384 :                 ++aStart;
     749       10384 :                 --aEnd;
     750             :             }
     751             :         }
     752        5192 :     }
     753             : 
     754         261 :     void transform(const ::basegfx::B2DHomMatrix& rMatrix)
     755             :     {
     756         261 :         const TextureData2DVector::const_iterator aEnd(maVector.end());
     757             : 
     758        1305 :         for(TextureData2DVector::iterator aStart(maVector.begin()); aStart != aEnd; ++aStart)
     759             :         {
     760        1044 :             (*aStart) *= rMatrix;
     761             :         }
     762         261 :     }
     763             : };
     764             : 
     765             : //////////////////////////////////////////////////////////////////////////////
     766             : 
     767             : class ImplB3DPolygon
     768             : {
     769             :     // The point vector. This vector exists always and defines the
     770             :     // count of members.
     771             :     CoordinateDataArray3D                           maPoints;
     772             : 
     773             :     // The BColor vector. This vectors are created on demand
     774             :     // and may be zero.
     775             :     BColorArray*                                    mpBColors;
     776             : 
     777             :     // The Normals vector. This vectors are created on demand
     778             :     // and may be zero.
     779             :     NormalsArray3D*                                 mpNormals;
     780             : 
     781             :     // The TextureCoordinates vector. This vectors are created on demand
     782             :     // and may be zero.
     783             :     TextureCoordinate2D*                            mpTextureCoordiantes;
     784             : 
     785             :     // The calculated plane normal. mbPlaneNormalValid says if it's valid.
     786             :     ::basegfx::B3DVector                            maPlaneNormal;
     787             : 
     788             :     // bitfield
     789             :     // flag which decides if this polygon is opened or closed
     790             :     unsigned                                        mbIsClosed : 1;
     791             : 
     792             :     // flag which says if maPlaneNormal is up-to-date
     793             :     unsigned                                        mbPlaneNormalValid : 1;
     794             : 
     795             : protected:
     796       39541 :     void invalidatePlaneNormal()
     797             :     {
     798       39541 :         if(mbPlaneNormalValid)
     799             :         {
     800        9418 :             mbPlaneNormalValid = false;
     801             :         }
     802       39541 :     }
     803             : 
     804             : public:
     805             :     // This constructor is only used from the static identity polygon, thus
     806             :     // the RefCount is set to 1 to never 'delete' this static incarnation.
     807           1 :     ImplB3DPolygon()
     808             :     :   maPoints(0L),
     809             :         mpBColors(0L),
     810             :         mpNormals(0L),
     811             :         mpTextureCoordiantes(0L),
     812           1 :         maPlaneNormal(::basegfx::B3DVector::getEmptyVector()),
     813             :         mbIsClosed(false),
     814           2 :         mbPlaneNormalValid(true)
     815             :     {
     816             :         // complete initialization with defaults
     817           1 :     }
     818             : 
     819       15314 :     ImplB3DPolygon(const ImplB3DPolygon& rToBeCopied)
     820             :     :   maPoints(rToBeCopied.maPoints),
     821             :         mpBColors(0L),
     822             :         mpNormals(0L),
     823             :         mpTextureCoordiantes(0L),
     824             :         maPlaneNormal(rToBeCopied.maPlaneNormal),
     825             :         mbIsClosed(rToBeCopied.mbIsClosed),
     826       15314 :         mbPlaneNormalValid(rToBeCopied.mbPlaneNormalValid)
     827             :     {
     828             :         // complete initialization using copy
     829       15314 :         if(rToBeCopied.mpBColors && rToBeCopied.mpBColors->isUsed())
     830             :         {
     831           0 :             mpBColors = new BColorArray(*rToBeCopied.mpBColors);
     832             :         }
     833             : 
     834       15314 :         if(rToBeCopied.mpNormals && rToBeCopied.mpNormals->isUsed())
     835             :         {
     836         529 :             mpNormals = new NormalsArray3D(*rToBeCopied.mpNormals);
     837             :         }
     838             : 
     839       15314 :         if(rToBeCopied.mpTextureCoordiantes && rToBeCopied.mpTextureCoordiantes->isUsed())
     840             :         {
     841         454 :             mpTextureCoordiantes = new TextureCoordinate2D(*rToBeCopied.mpTextureCoordiantes);
     842             :         }
     843       15314 :     }
     844             : 
     845           0 :     ImplB3DPolygon(const ImplB3DPolygon& rToBeCopied, sal_uInt32 nIndex, sal_uInt32 nCount)
     846             :     :   maPoints(rToBeCopied.maPoints, nIndex, nCount),
     847             :         mpBColors(0L),
     848             :         mpNormals(0L),
     849             :         mpTextureCoordiantes(0L),
     850           0 :         maPlaneNormal(::basegfx::B3DVector::getEmptyVector()),
     851             :         mbIsClosed(rToBeCopied.mbIsClosed),
     852           0 :         mbPlaneNormalValid(false)
     853             :     {
     854             :         // complete initialization using partly copy
     855           0 :         if(rToBeCopied.mpBColors && rToBeCopied.mpBColors->isUsed())
     856             :         {
     857           0 :             mpBColors = new BColorArray(*rToBeCopied.mpBColors, nIndex, nCount);
     858             : 
     859           0 :             if(!mpBColors->isUsed())
     860             :             {
     861           0 :                 delete mpBColors;
     862           0 :                 mpBColors = 0L;
     863             :             }
     864             :         }
     865             : 
     866           0 :         if(rToBeCopied.mpNormals && rToBeCopied.mpNormals->isUsed())
     867             :         {
     868           0 :             mpNormals = new NormalsArray3D(*rToBeCopied.mpNormals, nIndex, nCount);
     869             : 
     870           0 :             if(!mpNormals->isUsed())
     871             :             {
     872           0 :                 delete mpNormals;
     873           0 :                 mpNormals = 0L;
     874             :             }
     875             :         }
     876             : 
     877           0 :         if(rToBeCopied.mpTextureCoordiantes && rToBeCopied.mpTextureCoordiantes->isUsed())
     878             :         {
     879           0 :             mpTextureCoordiantes = new TextureCoordinate2D(*rToBeCopied.mpTextureCoordiantes, nIndex, nCount);
     880             : 
     881           0 :             if(!mpTextureCoordiantes->isUsed())
     882             :             {
     883           0 :                 delete mpTextureCoordiantes;
     884           0 :                 mpTextureCoordiantes = 0L;
     885             :             }
     886             :         }
     887           0 :     }
     888             : 
     889       15315 :     ~ImplB3DPolygon()
     890       15315 :     {
     891       15315 :         if(mpBColors)
     892             :         {
     893          66 :             delete mpBColors;
     894          66 :             mpBColors = 0L;
     895             :         }
     896             : 
     897       15315 :         if(mpNormals)
     898             :         {
     899        5720 :             delete mpNormals;
     900        5720 :             mpNormals = 0L;
     901             :         }
     902             : 
     903       15315 :         if(mpTextureCoordiantes)
     904             :         {
     905        5663 :             delete mpTextureCoordiantes;
     906        5663 :             mpTextureCoordiantes = 0L;
     907             :         }
     908       15315 :     }
     909             : 
     910      116291 :     sal_uInt32 count() const
     911             :     {
     912      116291 :         return maPoints.count();
     913             :     }
     914             : 
     915        9550 :     bool isClosed() const
     916             :     {
     917        9550 :         return mbIsClosed;
     918             :     }
     919             : 
     920        7674 :     void setClosed(bool bNew)
     921             :     {
     922        7674 :         if(bNew != (bool)mbIsClosed)
     923             :         {
     924        7674 :             mbIsClosed = bNew;
     925             :         }
     926        7674 :     }
     927             : 
     928       10520 :     inline bool impBColorsAreEqual(const ImplB3DPolygon& rCandidate) const
     929             :     {
     930       10520 :         bool bBColorsAreEqual(true);
     931             : 
     932       10520 :         if(mpBColors)
     933             :         {
     934           0 :             if(rCandidate.mpBColors)
     935             :             {
     936           0 :                 bBColorsAreEqual = (*mpBColors == *rCandidate.mpBColors);
     937             :             }
     938             :             else
     939             :             {
     940             :                 // candidate has no BColors, so it's assumed all unused.
     941           0 :                 bBColorsAreEqual = !mpBColors->isUsed();
     942             :             }
     943             :         }
     944             :         else
     945             :         {
     946       10520 :             if(rCandidate.mpBColors)
     947             :             {
     948             :                 // we have no TextureCoordiantes, so it's assumed all unused.
     949          66 :                 bBColorsAreEqual = !rCandidate.mpBColors->isUsed();
     950             :             }
     951             :         }
     952             : 
     953       10520 :         return bBColorsAreEqual;
     954             :     }
     955             : 
     956       10454 :     inline bool impNormalsAreEqual(const ImplB3DPolygon& rCandidate) const
     957             :     {
     958       10454 :         bool bNormalsAreEqual(true);
     959             : 
     960       10454 :         if(mpNormals)
     961             :         {
     962        5118 :             if(rCandidate.mpNormals)
     963             :             {
     964        5118 :                 bNormalsAreEqual = (*mpNormals == *rCandidate.mpNormals);
     965             :             }
     966             :             else
     967             :             {
     968             :                 // candidate has no normals, so it's assumed all unused.
     969           0 :                 bNormalsAreEqual = !mpNormals->isUsed();
     970             :             }
     971             :         }
     972             :         else
     973             :         {
     974        5336 :             if(rCandidate.mpNormals)
     975             :             {
     976             :                 // we have no normals, so it's assumed all unused.
     977        5288 :                 bNormalsAreEqual = !rCandidate.mpNormals->isUsed();
     978             :             }
     979             :         }
     980             : 
     981       10454 :         return bNormalsAreEqual;
     982             :     }
     983             : 
     984        5118 :     inline bool impTextureCoordinatesAreEqual(const ImplB3DPolygon& rCandidate) const
     985             :     {
     986        5118 :         bool bTextureCoordinatesAreEqual(true);
     987             : 
     988        5118 :         if(mpTextureCoordiantes)
     989             :         {
     990        5070 :             if(rCandidate.mpTextureCoordiantes)
     991             :             {
     992        5070 :                 bTextureCoordinatesAreEqual = (*mpTextureCoordiantes == *rCandidate.mpTextureCoordiantes);
     993             :             }
     994             :             else
     995             :             {
     996             :                 // candidate has no TextureCoordinates, so it's assumed all unused.
     997           0 :                 bTextureCoordinatesAreEqual = !mpTextureCoordiantes->isUsed();
     998             :             }
     999             :         }
    1000             :         else
    1001             :         {
    1002          48 :             if(rCandidate.mpTextureCoordiantes)
    1003             :             {
    1004             :                 // we have no TextureCoordiantes, so it's assumed all unused.
    1005           0 :                 bTextureCoordinatesAreEqual = !rCandidate.mpTextureCoordiantes->isUsed();
    1006             :             }
    1007             :         }
    1008             : 
    1009        5118 :         return bTextureCoordinatesAreEqual;
    1010             :     }
    1011             : 
    1012       10520 :     bool operator==(const ImplB3DPolygon& rCandidate) const
    1013             :     {
    1014       10520 :         if(mbIsClosed == rCandidate.mbIsClosed)
    1015             :         {
    1016       10520 :             if(maPoints == rCandidate.maPoints)
    1017             :             {
    1018       10520 :                 if(impBColorsAreEqual(rCandidate))
    1019             :                 {
    1020       10454 :                     if(impNormalsAreEqual(rCandidate))
    1021             :                     {
    1022        5118 :                         if(impTextureCoordinatesAreEqual(rCandidate))
    1023             :                         {
    1024        5118 :                             return true;
    1025             :                         }
    1026             :                     }
    1027             :                 }
    1028             :             }
    1029             :         }
    1030             : 
    1031        5402 :         return false;
    1032             :     }
    1033             : 
    1034      102208 :     const ::basegfx::B3DPoint& getPoint(sal_uInt32 nIndex) const
    1035             :     {
    1036      102208 :         return maPoints.getCoordinate(nIndex);
    1037             :     }
    1038             : 
    1039           0 :     void setPoint(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rValue)
    1040             :     {
    1041           0 :         maPoints.setCoordinate(nIndex, rValue);
    1042           0 :         invalidatePlaneNormal();
    1043           0 :     }
    1044             : 
    1045       33482 :     void insert(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rPoint, sal_uInt32 nCount)
    1046             :     {
    1047       33482 :         if(nCount)
    1048             :         {
    1049       33482 :             CoordinateData3D aCoordinate(rPoint);
    1050       33482 :             maPoints.insert(nIndex, aCoordinate, nCount);
    1051       33482 :             invalidatePlaneNormal();
    1052             : 
    1053       33482 :             if(mpBColors)
    1054             :             {
    1055           0 :                 mpBColors->insert(nIndex, ::basegfx::BColor::getEmptyBColor(), nCount);
    1056             :             }
    1057             : 
    1058       33482 :             if(mpNormals)
    1059             :             {
    1060           0 :                 mpNormals->insert(nIndex, ::basegfx::B3DVector::getEmptyVector(), nCount);
    1061             :             }
    1062             : 
    1063       33482 :             if(mpTextureCoordiantes)
    1064             :             {
    1065           0 :                 mpTextureCoordiantes->insert(nIndex, ::basegfx::B2DPoint::getEmptyPoint(), nCount);
    1066       33482 :             }
    1067             :         }
    1068       33482 :     }
    1069             : 
    1070         792 :     const ::basegfx::BColor& getBColor(sal_uInt32 nIndex) const
    1071             :     {
    1072         792 :         if(mpBColors)
    1073             :         {
    1074         726 :             return mpBColors->getBColor(nIndex);
    1075             :         }
    1076             :         else
    1077             :         {
    1078          66 :             return ::basegfx::BColor::getEmptyBColor();
    1079             :         }
    1080             :     }
    1081             : 
    1082         264 :     void setBColor(sal_uInt32 nIndex, const ::basegfx::BColor& rValue)
    1083             :     {
    1084         264 :         if(!mpBColors)
    1085             :         {
    1086          66 :             if(!rValue.equalZero())
    1087             :             {
    1088          66 :                 mpBColors = new BColorArray(maPoints.count());
    1089          66 :                 mpBColors->setBColor(nIndex, rValue);
    1090             :             }
    1091             :         }
    1092             :         else
    1093             :         {
    1094         198 :             mpBColors->setBColor(nIndex, rValue);
    1095             : 
    1096         198 :             if(!mpBColors->isUsed())
    1097             :             {
    1098           0 :                 delete mpBColors;
    1099           0 :                 mpBColors = 0L;
    1100             :             }
    1101             :         }
    1102         264 :     }
    1103             : 
    1104         842 :     bool areBColorsUsed() const
    1105             :     {
    1106         842 :         return (mpBColors && mpBColors->isUsed());
    1107             :     }
    1108             : 
    1109           0 :     void clearBColors()
    1110             :     {
    1111           0 :         if(mpBColors)
    1112             :         {
    1113           0 :             delete mpBColors;
    1114           0 :             mpBColors = 0L;
    1115             :         }
    1116           0 :     }
    1117             : 
    1118         701 :     const ::basegfx::B3DVector& getNormal() const
    1119             :     {
    1120         701 :         if(!mbPlaneNormalValid)
    1121             :         {
    1122         628 :             const_cast< ImplB3DPolygon* >(this)->maPlaneNormal = maPoints.getNormal();
    1123         628 :             const_cast< ImplB3DPolygon* >(this)->mbPlaneNormalValid = true;
    1124             :         }
    1125             : 
    1126         701 :         return maPlaneNormal;
    1127             :     }
    1128             : 
    1129       22760 :     const ::basegfx::B3DVector& getNormal(sal_uInt32 nIndex) const
    1130             :     {
    1131       22760 :         if(mpNormals)
    1132             :         {
    1133       17376 :             return mpNormals->getNormal(nIndex);
    1134             :         }
    1135             :         else
    1136             :         {
    1137        5384 :             return ::basegfx::B3DVector::getEmptyVector();
    1138             :         }
    1139             :     }
    1140             : 
    1141       16536 :     void setNormal(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue)
    1142             :     {
    1143       16536 :         if(!mpNormals)
    1144             :         {
    1145        5384 :             if(!rValue.equalZero())
    1146             :             {
    1147        5384 :                 mpNormals = new NormalsArray3D(maPoints.count());
    1148        5384 :                 mpNormals->setNormal(nIndex, rValue);
    1149             :             }
    1150             :         }
    1151             :         else
    1152             :         {
    1153       11152 :             mpNormals->setNormal(nIndex, rValue);
    1154             : 
    1155       11152 :             if(!mpNormals->isUsed())
    1156             :             {
    1157           0 :                 delete mpNormals;
    1158           0 :                 mpNormals = 0L;
    1159             :             }
    1160             :         }
    1161       16536 :     }
    1162             : 
    1163          66 :     void transformNormals(const ::basegfx::B3DHomMatrix& rMatrix)
    1164             :     {
    1165          66 :         if(mpNormals)
    1166             :         {
    1167          66 :             mpNormals->transform(rMatrix);
    1168             :         }
    1169          66 :     }
    1170             : 
    1171        1756 :     bool areNormalsUsed() const
    1172             :     {
    1173        1756 :         return (mpNormals && mpNormals->isUsed());
    1174             :     }
    1175             : 
    1176         193 :     void clearNormals()
    1177             :     {
    1178         193 :         if(mpNormals)
    1179             :         {
    1180         193 :             delete mpNormals;
    1181         193 :             mpNormals = 0L;
    1182             :         }
    1183         193 :     }
    1184             : 
    1185       22640 :     const ::basegfx::B2DPoint& getTextureCoordinate(sal_uInt32 nIndex) const
    1186             :     {
    1187       22640 :         if(mpTextureCoordiantes)
    1188             :         {
    1189       16328 :             return mpTextureCoordiantes->getTextureCoordinate(nIndex);
    1190             :         }
    1191             :         else
    1192             :         {
    1193        6312 :             return ::basegfx::B2DPoint::getEmptyPoint();
    1194             :         }
    1195             :     }
    1196             : 
    1197       16008 :     void setTextureCoordinate(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue)
    1198             :     {
    1199       16008 :         if(!mpTextureCoordiantes)
    1200             :         {
    1201        5336 :             if(!rValue.equalZero())
    1202             :             {
    1203        5336 :                 mpTextureCoordiantes = new TextureCoordinate2D(maPoints.count());
    1204        5336 :                 mpTextureCoordiantes->setTextureCoordinate(nIndex, rValue);
    1205             :             }
    1206             :         }
    1207             :         else
    1208             :         {
    1209       10672 :             mpTextureCoordiantes->setTextureCoordinate(nIndex, rValue);
    1210             : 
    1211       10672 :             if(!mpTextureCoordiantes->isUsed())
    1212             :             {
    1213           0 :                 delete mpTextureCoordiantes;
    1214           0 :                 mpTextureCoordiantes = 0L;
    1215             :             }
    1216             :         }
    1217       16008 :     }
    1218             : 
    1219        1549 :     bool areTextureCoordinatesUsed() const
    1220             :     {
    1221        1549 :         return (mpTextureCoordiantes && mpTextureCoordiantes->isUsed());
    1222             :     }
    1223             : 
    1224         127 :     void clearTextureCoordinates()
    1225             :     {
    1226         127 :         if(mpTextureCoordiantes)
    1227             :         {
    1228         127 :             delete mpTextureCoordiantes;
    1229         127 :             mpTextureCoordiantes = 0L;
    1230             :         }
    1231         127 :     }
    1232             : 
    1233         261 :     void transformTextureCoordinates(const ::basegfx::B2DHomMatrix& rMatrix)
    1234             :     {
    1235         261 :         if(mpTextureCoordiantes)
    1236             :         {
    1237         261 :             mpTextureCoordiantes->transform(rMatrix);
    1238             :         }
    1239         261 :     }
    1240             : 
    1241           0 :     void insert(sal_uInt32 nIndex, const ImplB3DPolygon& rSource)
    1242             :     {
    1243           0 :         const sal_uInt32 nCount(rSource.maPoints.count());
    1244             : 
    1245           0 :         if(nCount)
    1246             :         {
    1247           0 :             maPoints.insert(nIndex, rSource.maPoints);
    1248           0 :             invalidatePlaneNormal();
    1249             : 
    1250           0 :             if(rSource.mpBColors && rSource.mpBColors->isUsed())
    1251             :             {
    1252           0 :                 if(!mpBColors)
    1253             :                 {
    1254           0 :                     mpBColors = new BColorArray(maPoints.count());
    1255             :                 }
    1256             : 
    1257           0 :                 mpBColors->insert(nIndex, *rSource.mpBColors);
    1258             :             }
    1259             :             else
    1260             :             {
    1261           0 :                 if(mpBColors)
    1262             :                 {
    1263           0 :                     mpBColors->insert(nIndex, ::basegfx::BColor::getEmptyBColor(), nCount);
    1264             :                 }
    1265             :             }
    1266             : 
    1267           0 :             if(rSource.mpNormals && rSource.mpNormals->isUsed())
    1268             :             {
    1269           0 :                 if(!mpNormals)
    1270             :                 {
    1271           0 :                     mpNormals = new NormalsArray3D(maPoints.count());
    1272             :                 }
    1273             : 
    1274           0 :                 mpNormals->insert(nIndex, *rSource.mpNormals);
    1275             :             }
    1276             :             else
    1277             :             {
    1278           0 :                 if(mpNormals)
    1279             :                 {
    1280           0 :                     mpNormals->insert(nIndex, ::basegfx::B3DVector::getEmptyVector(), nCount);
    1281             :                 }
    1282             :             }
    1283             : 
    1284           0 :             if(rSource.mpTextureCoordiantes && rSource.mpTextureCoordiantes->isUsed())
    1285             :             {
    1286           0 :                 if(!mpTextureCoordiantes)
    1287             :                 {
    1288           0 :                     mpTextureCoordiantes = new TextureCoordinate2D(maPoints.count());
    1289             :                 }
    1290             : 
    1291           0 :                 mpTextureCoordiantes->insert(nIndex, *rSource.mpTextureCoordiantes);
    1292             :             }
    1293             :             else
    1294             :             {
    1295           0 :                 if(mpTextureCoordiantes)
    1296             :                 {
    1297           0 :                     mpTextureCoordiantes->insert(nIndex, ::basegfx::B2DPoint::getEmptyPoint(), nCount);
    1298             :                 }
    1299             :             }
    1300             :         }
    1301           0 :     }
    1302             : 
    1303         842 :     void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
    1304             :     {
    1305         842 :         if(nCount)
    1306             :         {
    1307         842 :             maPoints.remove(nIndex, nCount);
    1308         842 :             invalidatePlaneNormal();
    1309             : 
    1310         842 :             if(mpBColors)
    1311             :             {
    1312           0 :                 mpBColors->remove(nIndex, nCount);
    1313             : 
    1314           0 :                 if(!mpBColors->isUsed())
    1315             :                 {
    1316           0 :                     delete mpBColors;
    1317           0 :                     mpBColors = 0L;
    1318             :                 }
    1319             :             }
    1320             : 
    1321         842 :             if(mpNormals)
    1322             :             {
    1323           0 :                 mpNormals->remove(nIndex, nCount);
    1324             : 
    1325           0 :                 if(!mpNormals->isUsed())
    1326             :                 {
    1327           0 :                     delete mpNormals;
    1328           0 :                     mpNormals = 0L;
    1329             :                 }
    1330             :             }
    1331             : 
    1332         842 :             if(mpTextureCoordiantes)
    1333             :             {
    1334           0 :                 mpTextureCoordiantes->remove(nIndex, nCount);
    1335             : 
    1336           0 :                 if(!mpTextureCoordiantes->isUsed())
    1337             :                 {
    1338           0 :                     delete mpTextureCoordiantes;
    1339           0 :                     mpTextureCoordiantes = 0L;
    1340             :                 }
    1341             :             }
    1342             :         }
    1343         842 :     }
    1344             : 
    1345        5216 :     void flip()
    1346             :     {
    1347        5216 :         if(maPoints.count() > 1)
    1348             :         {
    1349        5216 :             maPoints.flip();
    1350             : 
    1351        5216 :             if(mbPlaneNormalValid)
    1352             :             {
    1353             :                 // mirror plane normal
    1354          24 :                 maPlaneNormal = -maPlaneNormal;
    1355             :             }
    1356             : 
    1357        5216 :             if(mpBColors)
    1358             :             {
    1359           0 :                 mpBColors->flip();
    1360             :             }
    1361             : 
    1362        5216 :             if(mpNormals)
    1363             :             {
    1364        5216 :                 mpNormals->flip();
    1365             :             }
    1366             : 
    1367        5216 :             if(mpTextureCoordiantes)
    1368             :             {
    1369        5192 :                 mpTextureCoordiantes->flip();
    1370             :             }
    1371             :         }
    1372        5216 :     }
    1373             : 
    1374           0 :     bool hasDoublePoints() const
    1375             :     {
    1376           0 :         if(mbIsClosed)
    1377             :         {
    1378             :             // check for same start and end point
    1379           0 :             const sal_uInt32 nIndex(maPoints.count() - 1L);
    1380             : 
    1381           0 :             if(maPoints.getCoordinate(0L) == maPoints.getCoordinate(nIndex))
    1382             :             {
    1383           0 :                 const bool bBColorEqual(!mpBColors || (mpBColors->getBColor(0L) == mpBColors->getBColor(nIndex)));
    1384             : 
    1385           0 :                 if(bBColorEqual)
    1386             :                 {
    1387           0 :                     const bool bNormalsEqual(!mpNormals || (mpNormals->getNormal(0L) == mpNormals->getNormal(nIndex)));
    1388             : 
    1389           0 :                     if(bNormalsEqual)
    1390             :                     {
    1391           0 :                         const bool bTextureCoordinatesEqual(!mpTextureCoordiantes || (mpTextureCoordiantes->getTextureCoordinate(0L) == mpTextureCoordiantes->getTextureCoordinate(nIndex)));
    1392             : 
    1393           0 :                         if(bTextureCoordinatesEqual)
    1394             :                         {
    1395           0 :                             return true;
    1396             :                         }
    1397             :                     }
    1398             :                 }
    1399             :             }
    1400             :         }
    1401             : 
    1402             :         // test for range
    1403           0 :         for(sal_uInt32 a(0L); a < maPoints.count() - 1L; a++)
    1404             :         {
    1405           0 :             if(maPoints.getCoordinate(a) == maPoints.getCoordinate(a + 1L))
    1406             :             {
    1407           0 :                 const bool bBColorEqual(!mpBColors || (mpBColors->getBColor(a) == mpBColors->getBColor(a + 1L)));
    1408             : 
    1409           0 :                 if(bBColorEqual)
    1410             :                 {
    1411           0 :                     const bool bNormalsEqual(!mpNormals || (mpNormals->getNormal(a) == mpNormals->getNormal(a + 1L)));
    1412             : 
    1413           0 :                     if(bNormalsEqual)
    1414             :                     {
    1415           0 :                         const bool bTextureCoordinatesEqual(!mpTextureCoordiantes || (mpTextureCoordiantes->getTextureCoordinate(a) == mpTextureCoordiantes->getTextureCoordinate(a + 1L)));
    1416             : 
    1417           0 :                         if(bTextureCoordinatesEqual)
    1418             :                         {
    1419           0 :                             return true;
    1420             :                         }
    1421             :                     }
    1422             :                 }
    1423             :             }
    1424             :         }
    1425             : 
    1426           0 :         return false;
    1427             :     }
    1428             : 
    1429           0 :     void removeDoublePointsAtBeginEnd()
    1430             :     {
    1431             :         // Only remove DoublePoints at Begin and End when poly is closed
    1432           0 :         if(mbIsClosed)
    1433             :         {
    1434             :             bool bRemove;
    1435             : 
    1436           0 :             do
    1437             :             {
    1438           0 :                 bRemove = false;
    1439             : 
    1440           0 :                 if(maPoints.count() > 1L)
    1441             :                 {
    1442           0 :                     const sal_uInt32 nIndex(maPoints.count() - 1L);
    1443           0 :                     bRemove = (maPoints.getCoordinate(0L) == maPoints.getCoordinate(nIndex));
    1444             : 
    1445           0 :                     if(bRemove && mpBColors && !(mpBColors->getBColor(0L) == mpBColors->getBColor(nIndex)))
    1446             :                     {
    1447           0 :                         bRemove = false;
    1448             :                     }
    1449             : 
    1450           0 :                     if(bRemove && mpNormals && !(mpNormals->getNormal(0L) == mpNormals->getNormal(nIndex)))
    1451             :                     {
    1452           0 :                         bRemove = false;
    1453             :                     }
    1454             : 
    1455           0 :                     if(bRemove && mpTextureCoordiantes && !(mpTextureCoordiantes->getTextureCoordinate(0L) == mpTextureCoordiantes->getTextureCoordinate(nIndex)))
    1456             :                     {
    1457           0 :                         bRemove = false;
    1458             :                     }
    1459             :                 }
    1460             : 
    1461           0 :                 if(bRemove)
    1462             :                 {
    1463           0 :                     const sal_uInt32 nIndex(maPoints.count() - 1L);
    1464           0 :                     remove(nIndex, 1L);
    1465             :                 }
    1466             :             } while(bRemove);
    1467             :         }
    1468           0 :     }
    1469             : 
    1470           0 :     void removeDoublePointsWholeTrack()
    1471             :     {
    1472           0 :         sal_uInt32 nIndex(0L);
    1473             : 
    1474             :         // test as long as there are at least two points and as long as the index
    1475             :         // is smaller or equal second last point
    1476           0 :         while((maPoints.count() > 1L) && (nIndex <= maPoints.count() - 2L))
    1477             :         {
    1478           0 :             const sal_uInt32 nNextIndex(nIndex + 1L);
    1479           0 :             bool bRemove(maPoints.getCoordinate(nIndex) == maPoints.getCoordinate(nNextIndex));
    1480             : 
    1481           0 :             if(bRemove && mpBColors && !(mpBColors->getBColor(nIndex) == mpBColors->getBColor(nNextIndex)))
    1482             :             {
    1483           0 :                 bRemove = false;
    1484             :             }
    1485             : 
    1486           0 :             if(bRemove && mpNormals && !(mpNormals->getNormal(nIndex) == mpNormals->getNormal(nNextIndex)))
    1487             :             {
    1488           0 :                 bRemove = false;
    1489             :             }
    1490             : 
    1491           0 :             if(bRemove && mpTextureCoordiantes && !(mpTextureCoordiantes->getTextureCoordinate(nIndex) == mpTextureCoordiantes->getTextureCoordinate(nNextIndex)))
    1492             :             {
    1493           0 :                 bRemove = false;
    1494             :             }
    1495             : 
    1496           0 :             if(bRemove)
    1497             :             {
    1498             :                 // if next is same as index and the control vectors are unused, delete index
    1499           0 :                 remove(nIndex, 1L);
    1500             :             }
    1501             :             else
    1502             :             {
    1503             :                 // if different, step forward
    1504           0 :                 nIndex++;
    1505             :             }
    1506             :         }
    1507           0 :     }
    1508             : 
    1509        5217 :     void transform(const ::basegfx::B3DHomMatrix& rMatrix)
    1510             :     {
    1511        5217 :         maPoints.transform(rMatrix);
    1512             : 
    1513             :         // Here, it seems to be possible to transform a valid plane normal and to avoid
    1514             :         // invalidation, but it's not true. If the transformation contains shears or e.g.
    1515             :         // perspective projection, the orthogonality to the transformed plane will not
    1516             :         // be preserved. It may be possible to test that at the matrix to not invalidate in
    1517             :         // all cases or to extract a matrix which does not 'shear' the vector which is
    1518             :         // a normal in this case. As long as this is not sure, i will just invalidate.
    1519        5217 :         invalidatePlaneNormal();
    1520        5217 :     }
    1521             : };
    1522             : 
    1523             : //////////////////////////////////////////////////////////////////////////////
    1524             : 
    1525             : namespace basegfx
    1526             : {
    1527             :     namespace { struct DefaultPolygon : public rtl::Static< B3DPolygon::ImplType,
    1528             :                                                             DefaultPolygon > {}; }
    1529             : 
    1530       14562 :     B3DPolygon::B3DPolygon() :
    1531       14562 :         mpPolygon(DefaultPolygon::get())
    1532             :     {
    1533       14562 :     }
    1534             : 
    1535       63038 :     B3DPolygon::B3DPolygon(const B3DPolygon& rPolygon) :
    1536       63038 :         mpPolygon(rPolygon.mpPolygon)
    1537             :     {
    1538       63038 :     }
    1539             : 
    1540       77600 :     B3DPolygon::~B3DPolygon()
    1541             :     {
    1542       77600 :     }
    1543             : 
    1544       10594 :     B3DPolygon& B3DPolygon::operator=(const B3DPolygon& rPolygon)
    1545             :     {
    1546       10594 :         mpPolygon = rPolygon.mpPolygon;
    1547       10594 :         return *this;
    1548             :     }
    1549             : 
    1550       10520 :     bool B3DPolygon::operator==(const B3DPolygon& rPolygon) const
    1551             :     {
    1552       10520 :         if(mpPolygon.same_object(rPolygon.mpPolygon))
    1553           0 :             return true;
    1554             : 
    1555       10520 :         return (*mpPolygon == *rPolygon.mpPolygon);
    1556             :     }
    1557             : 
    1558        5402 :     bool B3DPolygon::operator!=(const B3DPolygon& rPolygon) const
    1559             :     {
    1560        5402 :         return !(*this == rPolygon);
    1561             :     }
    1562             : 
    1563       77592 :     sal_uInt32 B3DPolygon::count() const
    1564             :     {
    1565       77592 :         return mpPolygon->count();
    1566             :     }
    1567             : 
    1568      102208 :     basegfx::B3DPoint B3DPolygon::getB3DPoint(sal_uInt32 nIndex) const
    1569             :     {
    1570             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
    1571             : 
    1572      102208 :         return mpPolygon->getPoint(nIndex);
    1573             :     }
    1574             : 
    1575           0 :     void B3DPolygon::setB3DPoint(sal_uInt32 nIndex, const basegfx::B3DPoint& rValue)
    1576             :     {
    1577             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
    1578             : 
    1579           0 :         if(getB3DPoint(nIndex) != rValue)
    1580           0 :             mpPolygon->setPoint(nIndex, rValue);
    1581           0 :     }
    1582             : 
    1583         528 :     BColor B3DPolygon::getBColor(sal_uInt32 nIndex) const
    1584             :     {
    1585             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
    1586             : 
    1587         528 :         return mpPolygon->getBColor(nIndex);
    1588             :     }
    1589             : 
    1590         264 :     void B3DPolygon::setBColor(sal_uInt32 nIndex, const BColor& rValue)
    1591             :     {
    1592             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
    1593             : 
    1594         264 :         if(mpPolygon->getBColor(nIndex) != rValue)
    1595         264 :             mpPolygon->setBColor(nIndex, rValue);
    1596         264 :     }
    1597             : 
    1598         832 :     bool B3DPolygon::areBColorsUsed() const
    1599             :     {
    1600         832 :         return mpPolygon->areBColorsUsed();
    1601             :     }
    1602             : 
    1603          10 :     void B3DPolygon::clearBColors()
    1604             :     {
    1605          10 :         if(mpPolygon->areBColorsUsed())
    1606           0 :             mpPolygon->clearBColors();
    1607          10 :     }
    1608             : 
    1609         701 :     B3DVector B3DPolygon::getNormal() const
    1610             :     {
    1611         701 :         return mpPolygon->getNormal();
    1612             :     }
    1613             : 
    1614        1032 :     B3DVector B3DPolygon::getNormal(sal_uInt32 nIndex) const
    1615             :     {
    1616             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
    1617             : 
    1618        1032 :         return mpPolygon->getNormal(nIndex);
    1619             :     }
    1620             : 
    1621       21728 :     void B3DPolygon::setNormal(sal_uInt32 nIndex, const B3DVector& rValue)
    1622             :     {
    1623             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
    1624             : 
    1625       21728 :         if(mpPolygon->getNormal(nIndex) != rValue)
    1626       16536 :             mpPolygon->setNormal(nIndex, rValue);
    1627       21728 :     }
    1628             : 
    1629          66 :     void B3DPolygon::transformNormals(const B3DHomMatrix& rMatrix)
    1630             :     {
    1631          66 :         if(mpPolygon->areNormalsUsed() && !rMatrix.isIdentity())
    1632          66 :             mpPolygon->transformNormals(rMatrix);
    1633          66 :     }
    1634             : 
    1635        1487 :     bool B3DPolygon::areNormalsUsed() const
    1636             :     {
    1637        1487 :         return mpPolygon->areNormalsUsed();
    1638             :     }
    1639             : 
    1640         203 :     void B3DPolygon::clearNormals()
    1641             :     {
    1642         203 :         if(mpPolygon->areNormalsUsed())
    1643         193 :             mpPolygon->clearNormals();
    1644         203 :     }
    1645             : 
    1646        1296 :     B2DPoint B3DPolygon::getTextureCoordinate(sal_uInt32 nIndex) const
    1647             :     {
    1648             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
    1649             : 
    1650        1296 :         return mpPolygon->getTextureCoordinate(nIndex);
    1651             :     }
    1652             : 
    1653       21344 :     void B3DPolygon::setTextureCoordinate(sal_uInt32 nIndex, const B2DPoint& rValue)
    1654             :     {
    1655             :         OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
    1656             : 
    1657       21344 :         if(mpPolygon->getTextureCoordinate(nIndex) != rValue)
    1658       16008 :             mpPolygon->setTextureCoordinate(nIndex, rValue);
    1659       21344 :     }
    1660             : 
    1661         261 :     void B3DPolygon::transformTextureCoordiantes(const B2DHomMatrix& rMatrix)
    1662             :     {
    1663         261 :         if(mpPolygon->areTextureCoordinatesUsed() && !rMatrix.isIdentity())
    1664         261 :             mpPolygon->transformTextureCoordinates(rMatrix);
    1665         261 :     }
    1666             : 
    1667        1151 :     bool B3DPolygon::areTextureCoordinatesUsed() const
    1668             :     {
    1669        1151 :         return mpPolygon->areTextureCoordinatesUsed();
    1670             :     }
    1671             : 
    1672         137 :     void B3DPolygon::clearTextureCoordinates()
    1673             :     {
    1674         137 :         if(mpPolygon->areTextureCoordinatesUsed())
    1675         127 :             mpPolygon->clearTextureCoordinates();
    1676         137 :     }
    1677             : 
    1678       33482 :     void B3DPolygon::append(const basegfx::B3DPoint& rPoint, sal_uInt32 nCount)
    1679             :     {
    1680       33482 :         if(nCount)
    1681       33482 :             mpPolygon->insert(mpPolygon->count(), rPoint, nCount);
    1682       33482 :     }
    1683             : 
    1684           0 :     void B3DPolygon::append(const B3DPolygon& rPoly, sal_uInt32 nIndex, sal_uInt32 nCount)
    1685             :     {
    1686           0 :         if(rPoly.count())
    1687             :         {
    1688           0 :             if(!nCount)
    1689             :             {
    1690           0 :                 nCount = rPoly.count();
    1691             :             }
    1692             : 
    1693           0 :             if(0L == nIndex && nCount == rPoly.count())
    1694             :             {
    1695           0 :                 mpPolygon->insert(mpPolygon->count(), *rPoly.mpPolygon);
    1696             :             }
    1697             :             else
    1698             :             {
    1699             :                 OSL_ENSURE(nIndex + nCount <= rPoly.mpPolygon->count(), "B3DPolygon Append outside range (!)");
    1700           0 :                 ImplB3DPolygon aTempPoly(*rPoly.mpPolygon, nIndex, nCount);
    1701           0 :                 mpPolygon->insert(mpPolygon->count(), aTempPoly);
    1702             :             }
    1703             :         }
    1704           0 :     }
    1705             : 
    1706         842 :     void B3DPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount)
    1707             :     {
    1708             :         OSL_ENSURE(nIndex + nCount <= mpPolygon->count(), "B3DPolygon Remove outside range (!)");
    1709             : 
    1710         842 :         if(nCount)
    1711         842 :             mpPolygon->remove(nIndex, nCount);
    1712         842 :     }
    1713             : 
    1714           0 :     void B3DPolygon::clear()
    1715             :     {
    1716           0 :         mpPolygon = DefaultPolygon::get();
    1717           0 :     }
    1718             : 
    1719        9550 :     bool B3DPolygon::isClosed() const
    1720             :     {
    1721        9550 :         return mpPolygon->isClosed();
    1722             :     }
    1723             : 
    1724        8410 :     void B3DPolygon::setClosed(bool bNew)
    1725             :     {
    1726        8410 :         if(isClosed() != bNew)
    1727        7674 :             mpPolygon->setClosed(bNew);
    1728        8410 :     }
    1729             : 
    1730        5216 :     void B3DPolygon::flip()
    1731             :     {
    1732        5216 :         if(count() > 1)
    1733        5216 :             mpPolygon->flip();
    1734        5216 :     }
    1735             : 
    1736           0 :     bool B3DPolygon::hasDoublePoints() const
    1737             :     {
    1738           0 :         return (mpPolygon->count() > 1L && mpPolygon->hasDoublePoints());
    1739             :     }
    1740             : 
    1741           0 :     void B3DPolygon::removeDoublePoints()
    1742             :     {
    1743           0 :         if(hasDoublePoints())
    1744             :         {
    1745           0 :             mpPolygon->removeDoublePointsAtBeginEnd();
    1746           0 :             mpPolygon->removeDoublePointsWholeTrack();
    1747             :         }
    1748           0 :     }
    1749             : 
    1750        5217 :     void B3DPolygon::transform(const basegfx::B3DHomMatrix& rMatrix)
    1751             :     {
    1752        5217 :         if(mpPolygon->count() && !rMatrix.isIdentity())
    1753             :         {
    1754        5217 :             mpPolygon->transform(rMatrix);
    1755             :         }
    1756        5217 :     }
    1757             : } // end of namespace basegfx
    1758             : 
    1759             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10