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

Generated by: LCOV version 1.10