LCOV - code coverage report
Current view: top level - basegfx/source/raster - rasterconvert3d.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 127 146 87.0 %
Date: 2012-08-25 Functions: 9 10 90.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 96 190 50.5 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : #include <basegfx/raster/rasterconvert3d.hxx>
      30                 :            : #include <basegfx/polygon/b3dpolygon.hxx>
      31                 :            : #include <basegfx/polygon/b3dpolypolygon.hxx>
      32                 :            : #include <basegfx/point/b3dpoint.hxx>
      33                 :            : 
      34                 :            : //////////////////////////////////////////////////////////////////////////////
      35                 :            : // implementations of the 3D raster converter
      36                 :            : 
      37                 :            : namespace basegfx
      38                 :            : {
      39                 :        551 :     void RasterConverter3D::addArea(const B3DPolygon& rFill, const B3DHomMatrix* pViewToEye)
      40                 :            :     {
      41                 :        551 :         const sal_uInt32 nPointCount(rFill.count());
      42                 :            : 
      43         [ +  + ]:       2755 :         for(sal_uInt32 a(0); a < nPointCount; a++)
      44                 :            :         {
      45                 :       2204 :             addEdge(rFill, a, (a + 1) % nPointCount, pViewToEye);
      46                 :            :         }
      47                 :        551 :     }
      48                 :            : 
      49                 :        551 :     void RasterConverter3D::addArea(const B3DPolyPolygon& rFill, const B3DHomMatrix* pViewToEye)
      50                 :            :     {
      51                 :        551 :         const sal_uInt32 nPolyCount(rFill.count());
      52                 :            : 
      53         [ +  + ]:       1102 :         for(sal_uInt32 a(0); a < nPolyCount; a++)
      54                 :            :         {
      55         [ +  - ]:        551 :             addArea(rFill.getB3DPolygon(a), pViewToEye);
      56                 :            :         }
      57                 :        551 :     }
      58                 :            : 
      59                 :         15 :     RasterConverter3D::RasterConverter3D()
      60                 :            :     :   InterpolatorProvider3D(),
      61         [ +  - ]:         15 :         maLineEntries()
      62                 :         15 :     {}
      63                 :            : 
      64                 :         15 :     RasterConverter3D::~RasterConverter3D()
      65         [ -  + ]:         15 :     {}
      66                 :            : 
      67                 :        641 :     void RasterConverter3D::rasterconvertB3DArea(sal_Int32 nStartLine, sal_Int32 nStopLine)
      68                 :            :     {
      69         [ +  - ]:        641 :         if(!maLineEntries.empty())
      70                 :            :         {
      71                 :            :             OSL_ENSURE(nStopLine >= nStartLine, "nStopLine is bigger than nStartLine (!)");
      72                 :            : 
      73                 :            :             // sort global entries by Y, X once. After this, the vector
      74                 :            :             // is seen as frozen. Pointers to it's entries will be used in the following code.
      75         [ +  - ]:        641 :             ::std::sort(maLineEntries.begin(), maLineEntries.end());
      76                 :            : 
      77                 :            :             // local parameters
      78                 :        641 :             ::std::vector< RasterConversionLineEntry3D >::iterator aCurrentEntry(maLineEntries.begin());
      79         [ +  - ]:        641 :             ::std::vector< RasterConversionLineEntry3D* > aCurrentLine;
      80         [ +  - ]:        641 :             ::std::vector< RasterConversionLineEntry3D* > aNextLine;
      81                 :        641 :             ::std::vector< RasterConversionLineEntry3D* >::iterator aRasterConversionLineEntry3D;
      82                 :        641 :             sal_uInt32 nPairCount(0);
      83                 :            : 
      84                 :            :             // get scanlines first LineNumber as start
      85         [ +  - ]:        641 :             sal_Int32 nLineNumber(::std::max(aCurrentEntry->getY(), nStartLine));
      86                 :            : 
      87 [ +  + ][ +  - ]:      52875 :             while((aCurrentLine.size() || aCurrentEntry != maLineEntries.end()) && (nLineNumber < nStopLine))
         [ +  + ][ +  + ]
                 [ +  + ]
           [ +  +  #  # ]
      88                 :            :             {
      89                 :            :                 // add all entries which start at current line to current scanline
      90 [ +  - ][ +  + ]:      54515 :                 while(aCurrentEntry != maLineEntries.end())
      91                 :            :                 {
      92                 :      29244 :                     const sal_Int32 nCurrentLineNumber(aCurrentEntry->getY());
      93                 :            : 
      94         [ +  + ]:      29244 :                     if(nCurrentLineNumber > nLineNumber)
      95                 :            :                     {
      96                 :            :                         // line is below current one, done (since array is sorted)
      97                 :      26963 :                         break;
      98                 :            :                     }
      99                 :            :                     else
     100                 :            :                     {
     101                 :            :                         // less or equal. Line is above or at current one. Advance it exactly to
     102                 :            :                         // current line
     103                 :       2281 :                         const sal_uInt32 nStep(nLineNumber - nCurrentLineNumber);
     104                 :            : 
     105 [ -  + ][ #  # ]:       2281 :                         if(!nStep || aCurrentEntry->decrementRasterConversionLineEntry3D(nStep))
                 [ +  - ]
     106                 :            :                         {
     107                 :            :                             // add when exactly on current line or when incremet to it did not
     108                 :            :                             // completely consume it
     109         [ -  + ]:       2281 :                             if(nStep)
     110                 :            :                             {
     111         [ #  # ]:          0 :                                 aCurrentEntry->incrementRasterConversionLineEntry3D(nStep, *this);
     112                 :            :                             }
     113                 :            : 
     114         [ +  - ]:       2281 :                             aCurrentLine.push_back(&(*(aCurrentEntry)));
     115                 :            :                         }
     116                 :            :                     }
     117                 :            : 
     118         [ +  - ]:       2281 :                     aCurrentEntry++;
     119                 :            :                 }
     120                 :            : 
     121                 :            :                 // sort current scanline using comparator. Only X is used there
     122                 :            :                 // since all entries are already in one processed line. This needs to be done
     123                 :            :                 // everytime since not only new spans may have benn added or old removed,
     124                 :            :                 // but incrementing may also have changed the order
     125         [ +  - ]:      52234 :                 ::std::sort(aCurrentLine.begin(), aCurrentLine.end(), lineComparator());
     126                 :            : 
     127                 :            :                 // process current scanline
     128                 :      52234 :                 aRasterConversionLineEntry3D = aCurrentLine.begin();
     129                 :      52234 :                 aNextLine.clear();
     130                 :      52234 :                 nPairCount = 0;
     131                 :            : 
     132 [ +  - ][ +  + ]:     156702 :                 while(aRasterConversionLineEntry3D != aCurrentLine.end())
     133                 :            :                 {
     134         [ +  - ]:     104468 :                     RasterConversionLineEntry3D& rPrevScanRasterConversionLineEntry3D(**aRasterConversionLineEntry3D++);
     135                 :            : 
     136                 :            :                     // look for 2nd span
     137 [ +  + ][ +  - ]:     104468 :                     if(aRasterConversionLineEntry3D != aCurrentLine.end())
     138                 :            :                     {
     139                 :            :                         // work on span from rPrevScanRasterConversionLineEntry3D to aRasterConversionLineEntry3D, fLineNumber is valid
     140         [ +  - ]:      52234 :                         processLineSpan(rPrevScanRasterConversionLineEntry3D, **aRasterConversionLineEntry3D, nLineNumber, nPairCount++);
     141                 :            :                     }
     142                 :            : 
     143                 :            :                     // increment to next line
     144         [ +  + ]:     104468 :                     if(rPrevScanRasterConversionLineEntry3D.decrementRasterConversionLineEntry3D(1))
     145                 :            :                     {
     146         [ +  - ]:     102295 :                         rPrevScanRasterConversionLineEntry3D.incrementRasterConversionLineEntry3D(1, *this);
     147         [ +  - ]:     102295 :                         aNextLine.push_back(&rPrevScanRasterConversionLineEntry3D);
     148                 :            :                     }
     149                 :            :                 }
     150                 :            : 
     151                 :            :                 // copy back next scanline if count has changed
     152         [ +  + ]:      52234 :                 if(aNextLine.size() != aCurrentLine.size())
     153                 :            :                 {
     154         [ +  - ]:       1590 :                     aCurrentLine = aNextLine;
     155                 :            :                 }
     156                 :            : 
     157                 :            :                 // increment fLineNumber
     158                 :      52234 :                 nLineNumber++;
     159                 :        641 :             }
     160                 :            :         }
     161                 :        641 :     }
     162                 :            : 
     163                 :       2204 :     void RasterConverter3D::addEdge(const B3DPolygon& rFill, sal_uInt32 a, sal_uInt32 b, const B3DHomMatrix* pViewToEye)
     164                 :            :     {
     165         [ +  - ]:       2204 :         B3DPoint aStart(rFill.getB3DPoint(a));
     166         [ +  - ]:       2204 :         B3DPoint aEnd(rFill.getB3DPoint(b));
     167                 :       2204 :         sal_Int32 nYStart(fround(aStart.getY()));
     168                 :       2204 :         sal_Int32 nYEnd(fround(aEnd.getY()));
     169                 :            : 
     170         [ +  + ]:       2204 :         if(nYStart != nYEnd)
     171                 :            :         {
     172         [ +  + ]:       2157 :             if(nYStart > nYEnd)
     173                 :            :             {
     174         [ +  - ]:       1075 :                 ::std::swap(aStart, aEnd);
     175                 :       1075 :                 ::std::swap(nYStart, nYEnd);
     176                 :       1075 :                 ::std::swap(a, b);
     177                 :            :             }
     178                 :            : 
     179                 :       2157 :             const sal_uInt32 nYDelta(nYEnd - nYStart);
     180                 :       2157 :             const double fInvYDelta(1.0 / nYDelta);
     181                 :            :             maLineEntries.push_back(RasterConversionLineEntry3D(
     182                 :       2157 :                 aStart.getX(), (aEnd.getX() - aStart.getX()) * fInvYDelta,
     183                 :       2157 :                 aStart.getZ(), (aEnd.getZ() - aStart.getZ()) * fInvYDelta,
     184         [ +  - ]:       2157 :                 nYStart, nYDelta));
     185                 :            : 
     186                 :            :             // if extra interpolation data is used, add it to the last created entry
     187                 :       2157 :             RasterConversionLineEntry3D& rEntry = maLineEntries[maLineEntries.size() - 1];
     188                 :            : 
     189 [ +  + ][ +  - ]:       2157 :             if(rFill.areBColorsUsed())
     190                 :            :             {
     191 [ +  - ][ +  - ]:        264 :                 rEntry.setColorIndex(addColorInterpolator(rFill.getBColor(a), rFill.getBColor(b), fInvYDelta));
                 [ +  - ]
     192                 :            :             }
     193                 :            : 
     194 [ +  - ][ -  + ]:       2157 :             if(rFill.areNormalsUsed())
     195                 :            :             {
     196 [ #  # ][ #  # ]:          0 :                 rEntry.setNormalIndex(addNormalInterpolator(rFill.getNormal(a), rFill.getNormal(b), fInvYDelta));
                 [ #  # ]
     197                 :            :             }
     198                 :            : 
     199 [ +  - ][ +  + ]:       2157 :             if(rFill.areTextureCoordinatesUsed())
     200                 :            :             {
     201         [ +  - ]:        264 :                 if(pViewToEye)
     202                 :            :                 {
     203         [ +  - ]:        264 :                     const double fEyeA(((*pViewToEye) * aStart).getZ());
     204         [ +  - ]:        264 :                     const double fEyeB(((*pViewToEye) * aEnd).getZ());
     205                 :            : 
     206                 :            :                     rEntry.setInverseTextureIndex(addInverseTextureInterpolator(
     207                 :            :                         rFill.getTextureCoordinate(a),
     208                 :            :                         rFill.getTextureCoordinate(b),
     209 [ +  - ][ +  - ]:        264 :                         fEyeA, fEyeB, fInvYDelta));
                 [ +  - ]
     210                 :            :                 }
     211                 :            :                 else
     212                 :            :                 {
     213                 :            :                     rEntry.setTextureIndex(addTextureInterpolator(
     214                 :            :                         rFill.getTextureCoordinate(a),
     215                 :            :                         rFill.getTextureCoordinate(b),
     216 [ #  # ][ #  # ]:          0 :                         fInvYDelta));
                 [ #  # ]
     217                 :            :                 }
     218                 :            :             }
     219                 :       2204 :         }
     220                 :       2204 :     }
     221                 :            : 
     222                 :         90 :     void RasterConverter3D::rasterconvertB3DEdge(const B3DPolygon& rLine, sal_uInt32 nA, sal_uInt32 nB, sal_Int32 nStartLine, sal_Int32 nStopLine, sal_uInt16 nLineWidth)
     223                 :            :     {
     224         [ +  - ]:         90 :         B3DPoint aStart(rLine.getB3DPoint(nA));
     225         [ +  - ]:         90 :         B3DPoint aEnd(rLine.getB3DPoint(nB));
     226                 :         90 :         const double fZBufferLineAdd(0x00ff);
     227                 :            :         static bool bForceToPolygon(false);
     228                 :            : 
     229 [ +  - ][ -  + ]:         90 :         if(nLineWidth > 1 || bForceToPolygon)
     230                 :            :         {
     231                 :            :             // this is not a hairline anymore, in most cases since it's an oversampled
     232                 :            :             // hairline to get e.g. AA for Z-Buffering. Create fill geometry.
     233         [ #  # ]:          0 :             if(!aStart.equal(aEnd))
     234                 :            :             {
     235                 :          0 :                 reset();
     236                 :          0 :                 maLineEntries.clear();
     237                 :            : 
     238                 :          0 :                 B2DVector aVector(aEnd.getX() - aStart.getX(), aEnd.getY() - aStart.getY());
     239         [ #  # ]:          0 :                 aVector.normalize();
     240         [ #  # ]:          0 :                 const B2DVector aPerpend(getPerpendicular(aVector) * ((static_cast<double>(nLineWidth) + 0.5) * 0.5));
     241                 :          0 :                 const double fZStartWithAdd(aStart.getZ() + fZBufferLineAdd);
     242                 :          0 :                 const double fZEndWithAdd(aEnd.getZ() + fZBufferLineAdd);
     243                 :            : 
     244         [ #  # ]:          0 :                 B3DPolygon aPolygon;
     245         [ #  # ]:          0 :                 aPolygon.append(B3DPoint(aStart.getX() + aPerpend.getX(), aStart.getY() + aPerpend.getY(), fZStartWithAdd));
     246         [ #  # ]:          0 :                 aPolygon.append(B3DPoint(aEnd.getX() + aPerpend.getX(), aEnd.getY() + aPerpend.getY(), fZEndWithAdd));
     247         [ #  # ]:          0 :                 aPolygon.append(B3DPoint(aEnd.getX() - aPerpend.getX(), aEnd.getY() - aPerpend.getY(), fZEndWithAdd));
     248         [ #  # ]:          0 :                 aPolygon.append(B3DPoint(aStart.getX() - aPerpend.getX(), aStart.getY() - aPerpend.getY(), fZStartWithAdd));
     249         [ #  # ]:          0 :                 aPolygon.setClosed(true);
     250                 :            : 
     251 [ #  # ][ #  # ]:          0 :                 addArea(aPolygon, 0);
     252                 :          0 :             }
     253                 :            :         }
     254                 :            :         else
     255                 :            :         {
     256                 :            :             // it's a hairline. Use direct RasterConversionLineEntry creation to
     257                 :            :             // rasterconvert lines as similar to areas as possible to avoid Z-Fighting
     258                 :         90 :             sal_Int32 nYStart(fround(aStart.getY()));
     259                 :         90 :             sal_Int32 nYEnd(fround(aEnd.getY()));
     260                 :            : 
     261         [ +  + ]:         90 :             if(nYStart == nYEnd)
     262                 :            :             {
     263                 :            :                 // horizontal line, check X
     264                 :         13 :                 const sal_Int32 nXStart(static_cast<sal_Int32>(aStart.getX()));
     265                 :         13 :                 const sal_Int32 nXEnd(static_cast<sal_Int32>(aEnd.getX()));
     266                 :            : 
     267         [ +  - ]:         13 :                 if(nXStart != nXEnd)
     268                 :            :                 {
     269                 :         13 :                     reset();
     270                 :         13 :                     maLineEntries.clear();
     271                 :            : 
     272                 :            :                     // horizontal line, create vertical entries. These will be sorted by
     273                 :            :                     // X anyways, so no need to distinguish the case here
     274                 :            :                     maLineEntries.push_back(RasterConversionLineEntry3D(
     275                 :         13 :                         aStart.getX(), 0.0,
     276                 :         13 :                         aStart.getZ() + fZBufferLineAdd, 0.0,
     277         [ +  - ]:         13 :                         nYStart, 1));
     278                 :            :                     maLineEntries.push_back(RasterConversionLineEntry3D(
     279                 :         13 :                         aEnd.getX(), 0.0,
     280                 :         13 :                         aEnd.getZ() + fZBufferLineAdd, 0.0,
     281         [ +  - ]:         13 :                         nYStart, 1));
     282                 :            :                 }
     283                 :            :             }
     284                 :            :             else
     285                 :            :             {
     286                 :         77 :                 reset();
     287                 :         77 :                 maLineEntries.clear();
     288                 :            : 
     289         [ +  + ]:         77 :                 if(nYStart > nYEnd)
     290                 :            :                 {
     291         [ +  - ]:         47 :                     ::std::swap(aStart, aEnd);
     292                 :         47 :                     ::std::swap(nYStart, nYEnd);
     293                 :            :                 }
     294                 :            : 
     295                 :         77 :                 const sal_uInt32 nYDelta(static_cast<sal_uInt32>(nYEnd - nYStart));
     296                 :         77 :                 const double fInvYDelta(1.0 / nYDelta);
     297                 :            : 
     298                 :            :                 // non-horizontal line, create two parallell entries. These will be sorted by
     299                 :            :                 // X anyways, so no need to distinguish the case here
     300                 :            :                 maLineEntries.push_back(RasterConversionLineEntry3D(
     301                 :         77 :                     aStart.getX(), (aEnd.getX() - aStart.getX()) * fInvYDelta,
     302                 :         77 :                     aStart.getZ() + fZBufferLineAdd, (aEnd.getZ() - aStart.getZ()) * fInvYDelta,
     303         [ +  - ]:         77 :                     nYStart, nYDelta));
     304                 :            : 
     305                 :         77 :                 RasterConversionLineEntry3D& rEntry = maLineEntries[maLineEntries.size() - 1];
     306                 :            : 
     307                 :            :                 // need to choose a X-Distance for the 2nd edge which guarantees all pixels
     308                 :            :                 // of the line to be set. This is exactly the X-Increment for one Y-Step.
     309                 :            :                 // Same is true for Z, so in both cases, add one increment to them. To also
     310                 :            :                 // guarantee one pixel per line, add a minimum of one for X.
     311         [ +  + ]:         77 :                 const double fDistanceX(fabs(rEntry.getX().getInc()) >= 1.0 ? rEntry.getX().getInc() : 1.0);
     312                 :            : 
     313                 :            :                 maLineEntries.push_back(RasterConversionLineEntry3D(
     314                 :         77 :                     rEntry.getX().getVal() + fDistanceX, rEntry.getX().getInc(),
     315                 :         77 :                     rEntry.getZ().getVal() + rEntry.getZ().getInc(), rEntry.getZ().getInc(),
     316         [ +  - ]:         90 :                     nYStart, nYDelta));
     317                 :            :             }
     318                 :            :         }
     319                 :            : 
     320         [ +  - ]:         90 :         if(!maLineEntries.empty())
     321                 :            :         {
     322         [ +  - ]:         90 :             rasterconvertB3DArea(nStartLine, nStopLine);
     323                 :         90 :         }
     324                 :         90 :     }
     325                 :            : 
     326                 :        551 :     void RasterConverter3D::rasterconvertB3DPolyPolygon(const B3DPolyPolygon& rFill, const B3DHomMatrix* pViewToEye, sal_Int32 nStartLine, sal_Int32 nStopLine)
     327                 :            :     {
     328                 :        551 :         reset();
     329                 :        551 :         maLineEntries.clear();
     330                 :        551 :         addArea(rFill, pViewToEye);
     331                 :        551 :         rasterconvertB3DArea(nStartLine, nStopLine);
     332                 :        551 :     }
     333                 :            : 
     334                 :         30 :     void RasterConverter3D::rasterconvertB3DPolygon(const B3DPolygon& rLine, sal_Int32 nStartLine, sal_Int32 nStopLine, sal_uInt16 nLineWidth)
     335                 :            :     {
     336                 :         30 :         const sal_uInt32 nPointCount(rLine.count());
     337                 :            : 
     338         [ +  - ]:         30 :         if(nPointCount)
     339                 :            :         {
     340         [ -  + ]:         30 :             const sal_uInt32 nEdgeCount(rLine.isClosed() ? nPointCount : nPointCount - 1);
     341                 :            : 
     342         [ +  + ]:        120 :             for(sal_uInt32 a(0); a < nEdgeCount; a++)
     343                 :            :             {
     344                 :         90 :                 rasterconvertB3DEdge(rLine, a, (a + 1) % nPointCount, nStartLine, nStopLine, nLineWidth);
     345                 :            :             }
     346                 :            :         }
     347                 :         30 :     }
     348                 :            : } // end of namespace basegfx
     349                 :            : 
     350                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10