109dbbe93SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
309dbbe93SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
409dbbe93SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
509dbbe93SAndrew Rist  * distributed with this work for additional information
609dbbe93SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
709dbbe93SAndrew Rist  * to you under the Apache License, Version 2.0 (the
809dbbe93SAndrew Rist  * "License"); you may not use this file except in compliance
909dbbe93SAndrew Rist  * with the License.  You may obtain a copy of the License at
1009dbbe93SAndrew Rist  *
1109dbbe93SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
1209dbbe93SAndrew Rist  *
1309dbbe93SAndrew Rist  * Unless required by applicable law or agreed to in writing,
1409dbbe93SAndrew Rist  * software distributed under the License is distributed on an
1509dbbe93SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1609dbbe93SAndrew Rist  * KIND, either express or implied.  See the License for the
1709dbbe93SAndrew Rist  * specific language governing permissions and limitations
1809dbbe93SAndrew Rist  * under the License.
1909dbbe93SAndrew Rist  *
2009dbbe93SAndrew Rist  *************************************************************/
2109dbbe93SAndrew Rist 
2209dbbe93SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_basegfx.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <basegfx/raster/rasterconvert3d.hxx>
28cdf0e10cSrcweir #include <basegfx/polygon/b3dpolygon.hxx>
29cdf0e10cSrcweir #include <basegfx/polygon/b3dpolypolygon.hxx>
30cdf0e10cSrcweir #include <basegfx/point/b3dpoint.hxx>
31cdf0e10cSrcweir 
32cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
33cdf0e10cSrcweir // implementations of the 3D raster converter
34cdf0e10cSrcweir 
35cdf0e10cSrcweir namespace basegfx
36cdf0e10cSrcweir {
37cdf0e10cSrcweir     void RasterConverter3D::addArea(const B3DPolygon& rFill, const B3DHomMatrix* pViewToEye)
38cdf0e10cSrcweir     {
39cdf0e10cSrcweir 	    const sal_uInt32 nPointCount(rFill.count());
40cdf0e10cSrcweir 
41cdf0e10cSrcweir 	    for(sal_uInt32 a(0); a < nPointCount; a++)
42cdf0e10cSrcweir 	    {
43cdf0e10cSrcweir 		    addEdge(rFill, a, (a + 1) % nPointCount, pViewToEye);
44cdf0e10cSrcweir 	    }
45cdf0e10cSrcweir     }
46cdf0e10cSrcweir 
47cdf0e10cSrcweir     void RasterConverter3D::addArea(const B3DPolyPolygon& rFill, const B3DHomMatrix* pViewToEye)
48cdf0e10cSrcweir     {
49cdf0e10cSrcweir 	    const sal_uInt32 nPolyCount(rFill.count());
50cdf0e10cSrcweir 
51cdf0e10cSrcweir 	    for(sal_uInt32 a(0); a < nPolyCount; a++)
52cdf0e10cSrcweir 	    {
53cdf0e10cSrcweir 		    addArea(rFill.getB3DPolygon(a), pViewToEye);
54cdf0e10cSrcweir 	    }
55cdf0e10cSrcweir     }
56cdf0e10cSrcweir 
57cdf0e10cSrcweir     RasterConverter3D::RasterConverter3D()
58cdf0e10cSrcweir     :	InterpolatorProvider3D(),
59cdf0e10cSrcweir 	    maLineEntries()
60cdf0e10cSrcweir     {}
61cdf0e10cSrcweir 
62cdf0e10cSrcweir     RasterConverter3D::~RasterConverter3D()
63cdf0e10cSrcweir     {}
64cdf0e10cSrcweir 
65cdf0e10cSrcweir     void RasterConverter3D::rasterconvertB3DArea(sal_Int32 nStartLine, sal_Int32 nStopLine)
66cdf0e10cSrcweir     {
67cdf0e10cSrcweir 	    if(maLineEntries.size())
68cdf0e10cSrcweir 	    {
69cdf0e10cSrcweir 		    OSL_ENSURE(nStopLine >= nStartLine, "nStopLine is bigger than nStartLine (!)");
70cdf0e10cSrcweir 
71cdf0e10cSrcweir             // sort global entries by Y, X once. After this, the vector
72cdf0e10cSrcweir 		    // is seen as frozen. Pointers to it's entries will be used in the following code.
73cdf0e10cSrcweir 		    ::std::sort(maLineEntries.begin(), maLineEntries.end());
74cdf0e10cSrcweir 
75cdf0e10cSrcweir 		    // local parameters
76cdf0e10cSrcweir 		    ::std::vector< RasterConversionLineEntry3D >::iterator aCurrentEntry(maLineEntries.begin());
77cdf0e10cSrcweir 		    ::std::vector< RasterConversionLineEntry3D* > aCurrentLine;
78cdf0e10cSrcweir 		    ::std::vector< RasterConversionLineEntry3D* > aNextLine;
79cdf0e10cSrcweir 		    ::std::vector< RasterConversionLineEntry3D* >::iterator aRasterConversionLineEntry3D;
80cdf0e10cSrcweir 		    sal_uInt32 nPairCount(0);
81cdf0e10cSrcweir 
82cdf0e10cSrcweir 		    // get scanlines first LineNumber as start
83cdf0e10cSrcweir 		    sal_Int32 nLineNumber(::std::max(aCurrentEntry->getY(), nStartLine));
84cdf0e10cSrcweir 
85cdf0e10cSrcweir 		    while((aCurrentLine.size() || aCurrentEntry != maLineEntries.end()) && (nLineNumber < nStopLine))
86cdf0e10cSrcweir 		    {
87cdf0e10cSrcweir 			    // add all entries which start at current line to current scanline
88cdf0e10cSrcweir 			    while(aCurrentEntry != maLineEntries.end())
89cdf0e10cSrcweir 			    {
90cdf0e10cSrcweir 				    const sal_Int32 nCurrentLineNumber(aCurrentEntry->getY());
91cdf0e10cSrcweir 
92cdf0e10cSrcweir 				    if(nCurrentLineNumber > nLineNumber)
93cdf0e10cSrcweir 				    {
94cdf0e10cSrcweir 					    // line is below current one, done (since array is sorted)
95cdf0e10cSrcweir 					    break;
96cdf0e10cSrcweir 				    }
97cdf0e10cSrcweir 				    else
98cdf0e10cSrcweir 				    {
99cdf0e10cSrcweir 					    // less or equal. Line is above or at current one. Advance it exactly to
100cdf0e10cSrcweir 					    // current line
101cdf0e10cSrcweir 					    const sal_uInt32 nStep(nLineNumber - nCurrentLineNumber);
102cdf0e10cSrcweir 
103cdf0e10cSrcweir 					    if(!nStep || aCurrentEntry->decrementRasterConversionLineEntry3D(nStep))
104cdf0e10cSrcweir 					    {
105cdf0e10cSrcweir 						    // add when exactly on current line or when incremet to it did not
106cdf0e10cSrcweir 						    // completely consume it
107cdf0e10cSrcweir 						    if(nStep)
108cdf0e10cSrcweir 						    {
109cdf0e10cSrcweir 							    aCurrentEntry->incrementRasterConversionLineEntry3D(nStep, *this);
110cdf0e10cSrcweir 						    }
111cdf0e10cSrcweir 
112cdf0e10cSrcweir 						    aCurrentLine.push_back(&(*(aCurrentEntry)));
113cdf0e10cSrcweir 					    }
114cdf0e10cSrcweir 				    }
115cdf0e10cSrcweir 
116cdf0e10cSrcweir 				    aCurrentEntry++;
117cdf0e10cSrcweir 			    }
118cdf0e10cSrcweir 
119cdf0e10cSrcweir 			    // sort current scanline using comparator. Only X is used there
120cdf0e10cSrcweir 			    // since all entries are already in one processed line. This needs to be done
121*07a3d7f1SPedro Giffuni 			    // every time since not only new spans may have benn added or old removed,
122cdf0e10cSrcweir 			    // but incrementing may also have changed the order
123cdf0e10cSrcweir 			    ::std::sort(aCurrentLine.begin(), aCurrentLine.end(), lineComparator());
124cdf0e10cSrcweir 
125cdf0e10cSrcweir 			    // process current scanline
126cdf0e10cSrcweir 			    aRasterConversionLineEntry3D = aCurrentLine.begin();
127cdf0e10cSrcweir 			    aNextLine.clear();
128cdf0e10cSrcweir 			    nPairCount = 0;
129cdf0e10cSrcweir 
130cdf0e10cSrcweir 			    while(aRasterConversionLineEntry3D != aCurrentLine.end())
131cdf0e10cSrcweir 			    {
132cdf0e10cSrcweir 				    RasterConversionLineEntry3D& rPrevScanRasterConversionLineEntry3D(**aRasterConversionLineEntry3D++);
133cdf0e10cSrcweir 
134cdf0e10cSrcweir 				    // look for 2nd span
135cdf0e10cSrcweir 				    if(aRasterConversionLineEntry3D != aCurrentLine.end())
136cdf0e10cSrcweir 				    {
137cdf0e10cSrcweir 					    // work on span from rPrevScanRasterConversionLineEntry3D to aRasterConversionLineEntry3D, fLineNumber is valid
138cdf0e10cSrcweir 					    processLineSpan(rPrevScanRasterConversionLineEntry3D, **aRasterConversionLineEntry3D, nLineNumber, nPairCount++);
139cdf0e10cSrcweir 				    }
140cdf0e10cSrcweir 
141cdf0e10cSrcweir 				    // increment to next line
142cdf0e10cSrcweir 				    if(rPrevScanRasterConversionLineEntry3D.decrementRasterConversionLineEntry3D(1))
143cdf0e10cSrcweir 				    {
144cdf0e10cSrcweir 					    rPrevScanRasterConversionLineEntry3D.incrementRasterConversionLineEntry3D(1, *this);
145cdf0e10cSrcweir 					    aNextLine.push_back(&rPrevScanRasterConversionLineEntry3D);
146cdf0e10cSrcweir 				    }
147cdf0e10cSrcweir 			    }
148cdf0e10cSrcweir 
149cdf0e10cSrcweir 			    // copy back next scanline if count has changed
150cdf0e10cSrcweir 			    if(aNextLine.size() != aCurrentLine.size())
151cdf0e10cSrcweir 			    {
152cdf0e10cSrcweir 				    aCurrentLine = aNextLine;
153cdf0e10cSrcweir 			    }
154cdf0e10cSrcweir 
155cdf0e10cSrcweir 			    // increment fLineNumber
156cdf0e10cSrcweir 			    nLineNumber++;
157cdf0e10cSrcweir 		    }
158cdf0e10cSrcweir 	    }
159cdf0e10cSrcweir     }
160cdf0e10cSrcweir 
161cdf0e10cSrcweir     void RasterConverter3D::addEdge(const B3DPolygon& rFill, sal_uInt32 a, sal_uInt32 b, const B3DHomMatrix* pViewToEye)
162cdf0e10cSrcweir     {
163cdf0e10cSrcweir 	    B3DPoint aStart(rFill.getB3DPoint(a));
164cdf0e10cSrcweir 	    B3DPoint aEnd(rFill.getB3DPoint(b));
165cdf0e10cSrcweir 	    sal_Int32 nYStart(fround(aStart.getY()));
166cdf0e10cSrcweir 	    sal_Int32 nYEnd(fround(aEnd.getY()));
167cdf0e10cSrcweir 
168cdf0e10cSrcweir 	    if(nYStart != nYEnd)
169cdf0e10cSrcweir 	    {
170cdf0e10cSrcweir 		    if(nYStart > nYEnd)
171cdf0e10cSrcweir 		    {
172cdf0e10cSrcweir 			    ::std::swap(aStart, aEnd);
173cdf0e10cSrcweir 			    ::std::swap(nYStart, nYEnd);
174cdf0e10cSrcweir 			    ::std::swap(a, b);
175cdf0e10cSrcweir 		    }
176cdf0e10cSrcweir 
177cdf0e10cSrcweir 		    const sal_uInt32 nYDelta(nYEnd - nYStart);
178cdf0e10cSrcweir 		    const double fInvYDelta(1.0 / nYDelta);
179cdf0e10cSrcweir 		    maLineEntries.push_back(RasterConversionLineEntry3D(
180cdf0e10cSrcweir 			    aStart.getX(), (aEnd.getX() - aStart.getX()) * fInvYDelta,
181cdf0e10cSrcweir 			    aStart.getZ(), (aEnd.getZ() - aStart.getZ()) * fInvYDelta,
182cdf0e10cSrcweir 			    nYStart, nYDelta));
183cdf0e10cSrcweir 
184cdf0e10cSrcweir 		    // if extra interpolation data is used, add it to the last created entry
185cdf0e10cSrcweir 		    RasterConversionLineEntry3D& rEntry = maLineEntries[maLineEntries.size() - 1];
186cdf0e10cSrcweir 
187cdf0e10cSrcweir 		    if(rFill.areBColorsUsed())
188cdf0e10cSrcweir 		    {
189cdf0e10cSrcweir 			    rEntry.setColorIndex(addColorInterpolator(rFill.getBColor(a), rFill.getBColor(b), fInvYDelta));
190cdf0e10cSrcweir 		    }
191cdf0e10cSrcweir 
192cdf0e10cSrcweir 		    if(rFill.areNormalsUsed())
193cdf0e10cSrcweir 		    {
194cdf0e10cSrcweir 			    rEntry.setNormalIndex(addNormalInterpolator(rFill.getNormal(a), rFill.getNormal(b), fInvYDelta));
195cdf0e10cSrcweir 		    }
196cdf0e10cSrcweir 
197cdf0e10cSrcweir 		    if(rFill.areTextureCoordinatesUsed())
198cdf0e10cSrcweir 		    {
199cdf0e10cSrcweir 			    if(pViewToEye)
200cdf0e10cSrcweir 			    {
201cdf0e10cSrcweir 				    const double fEyeA(((*pViewToEye) * aStart).getZ());
202cdf0e10cSrcweir 				    const double fEyeB(((*pViewToEye) * aEnd).getZ());
203cdf0e10cSrcweir 
204cdf0e10cSrcweir 				    rEntry.setInverseTextureIndex(addInverseTextureInterpolator(
205cdf0e10cSrcweir 					    rFill.getTextureCoordinate(a),
206cdf0e10cSrcweir 					    rFill.getTextureCoordinate(b),
207cdf0e10cSrcweir 					    fEyeA, fEyeB, fInvYDelta));
208cdf0e10cSrcweir 			    }
209cdf0e10cSrcweir 			    else
210cdf0e10cSrcweir 			    {
211cdf0e10cSrcweir 				    rEntry.setTextureIndex(addTextureInterpolator(
212cdf0e10cSrcweir 					    rFill.getTextureCoordinate(a),
213cdf0e10cSrcweir 					    rFill.getTextureCoordinate(b),
214cdf0e10cSrcweir 					    fInvYDelta));
215cdf0e10cSrcweir 			    }
216cdf0e10cSrcweir 		    }
217cdf0e10cSrcweir 	    }
218cdf0e10cSrcweir     }
219cdf0e10cSrcweir 
220cdf0e10cSrcweir     void RasterConverter3D::rasterconvertB3DEdge(const B3DPolygon& rLine, sal_uInt32 nA, sal_uInt32 nB, sal_Int32 nStartLine, sal_Int32 nStopLine, sal_uInt16 nLineWidth)
221cdf0e10cSrcweir     {
222cdf0e10cSrcweir         B3DPoint aStart(rLine.getB3DPoint(nA));
223cdf0e10cSrcweir         B3DPoint aEnd(rLine.getB3DPoint(nB));
224cdf0e10cSrcweir         const double fZBufferLineAdd(0x00ff);
225cdf0e10cSrcweir 		static bool bForceToPolygon(false);
226cdf0e10cSrcweir 
227cdf0e10cSrcweir         if(nLineWidth > 1 || bForceToPolygon)
228cdf0e10cSrcweir         {
229cdf0e10cSrcweir             // this is not a hairline anymore, in most cases since it's an oversampled
230cdf0e10cSrcweir             // hairline to get e.g. AA for Z-Buffering. Create fill geometry.
231cdf0e10cSrcweir             if(!aStart.equal(aEnd))
232cdf0e10cSrcweir             {
233cdf0e10cSrcweir 		        reset();
234cdf0e10cSrcweir 		        maLineEntries.clear();
235cdf0e10cSrcweir 
236cdf0e10cSrcweir                 B2DVector aVector(aEnd.getX() - aStart.getX(), aEnd.getY() - aStart.getY());
237cdf0e10cSrcweir                 aVector.normalize();
238cdf0e10cSrcweir             	const B2DVector aPerpend(getPerpendicular(aVector) * ((static_cast<double>(nLineWidth) + 0.5) * 0.5));
239cdf0e10cSrcweir                 const double fZStartWithAdd(aStart.getZ() + fZBufferLineAdd);
240cdf0e10cSrcweir                 const double fZEndWithAdd(aEnd.getZ() + fZBufferLineAdd);
241cdf0e10cSrcweir 
242cdf0e10cSrcweir                 B3DPolygon aPolygon;
243cdf0e10cSrcweir                 aPolygon.append(B3DPoint(aStart.getX() + aPerpend.getX(), aStart.getY() + aPerpend.getY(), fZStartWithAdd));
244cdf0e10cSrcweir                 aPolygon.append(B3DPoint(aEnd.getX() + aPerpend.getX(), aEnd.getY() + aPerpend.getY(), fZEndWithAdd));
245cdf0e10cSrcweir                 aPolygon.append(B3DPoint(aEnd.getX() - aPerpend.getX(), aEnd.getY() - aPerpend.getY(), fZEndWithAdd));
246cdf0e10cSrcweir                 aPolygon.append(B3DPoint(aStart.getX() - aPerpend.getX(), aStart.getY() - aPerpend.getY(), fZStartWithAdd));
247cdf0e10cSrcweir                 aPolygon.setClosed(true);
248cdf0e10cSrcweir 
249cdf0e10cSrcweir                 addArea(aPolygon, 0);
250cdf0e10cSrcweir             }
251cdf0e10cSrcweir         }
252cdf0e10cSrcweir         else
253cdf0e10cSrcweir         {
254cdf0e10cSrcweir             // it's a hairline. Use direct RasterConversionLineEntry creation to
255cdf0e10cSrcweir             // rasterconvert lines as similar to areas as possible to avoid Z-Fighting
256cdf0e10cSrcweir 	        sal_Int32 nYStart(fround(aStart.getY()));
257cdf0e10cSrcweir 	        sal_Int32 nYEnd(fround(aEnd.getY()));
258cdf0e10cSrcweir 
259cdf0e10cSrcweir 	        if(nYStart == nYEnd)
260cdf0e10cSrcweir 	        {
261cdf0e10cSrcweir 		        // horizontal line, check X
262cdf0e10cSrcweir 		        const sal_Int32 nXStart(static_cast<sal_Int32>(aStart.getX()));
263cdf0e10cSrcweir 		        const sal_Int32 nXEnd(static_cast<sal_Int32>(aEnd.getX()));
264cdf0e10cSrcweir 
265cdf0e10cSrcweir 		        if(nXStart != nXEnd)
266cdf0e10cSrcweir 		        {
267cdf0e10cSrcweir 			        reset();
268cdf0e10cSrcweir 			        maLineEntries.clear();
269cdf0e10cSrcweir 
270cdf0e10cSrcweir 			        // horizontal line, create vertical entries. These will be sorted by
271cdf0e10cSrcweir 			        // X anyways, so no need to distinguish the case here
272cdf0e10cSrcweir 			        maLineEntries.push_back(RasterConversionLineEntry3D(
273cdf0e10cSrcweir 				        aStart.getX(), 0.0,
274cdf0e10cSrcweir 				        aStart.getZ() + fZBufferLineAdd, 0.0,
275cdf0e10cSrcweir 				        nYStart, 1));
276cdf0e10cSrcweir 			        maLineEntries.push_back(RasterConversionLineEntry3D(
277cdf0e10cSrcweir 				        aEnd.getX(), 0.0,
278cdf0e10cSrcweir 				        aEnd.getZ() + fZBufferLineAdd, 0.0,
279cdf0e10cSrcweir 				        nYStart, 1));
280cdf0e10cSrcweir 		        }
281cdf0e10cSrcweir 	        }
282cdf0e10cSrcweir 	        else
283cdf0e10cSrcweir 	        {
284cdf0e10cSrcweir 		        reset();
285cdf0e10cSrcweir 		        maLineEntries.clear();
286cdf0e10cSrcweir 
287cdf0e10cSrcweir 		        if(nYStart > nYEnd)
288cdf0e10cSrcweir 		        {
289cdf0e10cSrcweir 			        ::std::swap(aStart, aEnd);
290cdf0e10cSrcweir 			        ::std::swap(nYStart, nYEnd);
291cdf0e10cSrcweir 		        }
292cdf0e10cSrcweir 
293cdf0e10cSrcweir 		        const sal_uInt32 nYDelta(static_cast<sal_uInt32>(nYEnd - nYStart));
294cdf0e10cSrcweir 		        const double fInvYDelta(1.0 / nYDelta);
295cdf0e10cSrcweir 
296cdf0e10cSrcweir 		        // non-horizontal line, create two parallell entries. These will be sorted by
297cdf0e10cSrcweir 		        // X anyways, so no need to distinguish the case here
298cdf0e10cSrcweir 		        maLineEntries.push_back(RasterConversionLineEntry3D(
299cdf0e10cSrcweir 			        aStart.getX(), (aEnd.getX() - aStart.getX()) * fInvYDelta,
300cdf0e10cSrcweir 			        aStart.getZ() + fZBufferLineAdd, (aEnd.getZ() - aStart.getZ()) * fInvYDelta,
301cdf0e10cSrcweir 			        nYStart, nYDelta));
302cdf0e10cSrcweir 
303cdf0e10cSrcweir 		        RasterConversionLineEntry3D& rEntry = maLineEntries[maLineEntries.size() - 1];
304cdf0e10cSrcweir 
305cdf0e10cSrcweir 		        // need to choose a X-Distance for the 2nd edge which guarantees all pixels
306cdf0e10cSrcweir 		        // of the line to be set. This is exactly the X-Increment for one Y-Step.
307cdf0e10cSrcweir 		        // Same is true for Z, so in both cases, add one increment to them. To also
308cdf0e10cSrcweir 		        // guarantee one pixel per line, add a minimum of one for X.
309cdf0e10cSrcweir 		        const double fDistanceX(fabs(rEntry.getX().getInc()) >= 1.0 ? rEntry.getX().getInc() : 1.0);
310cdf0e10cSrcweir 
311cdf0e10cSrcweir 		        maLineEntries.push_back(RasterConversionLineEntry3D(
312cdf0e10cSrcweir 			        rEntry.getX().getVal() + fDistanceX, rEntry.getX().getInc(),
313cdf0e10cSrcweir 			        rEntry.getZ().getVal() + rEntry.getZ().getInc(), rEntry.getZ().getInc(),
314cdf0e10cSrcweir 			        nYStart, nYDelta));
315cdf0e10cSrcweir 	        }
316cdf0e10cSrcweir         }
317cdf0e10cSrcweir 
318cdf0e10cSrcweir         if(maLineEntries.size())
319cdf0e10cSrcweir         {
320cdf0e10cSrcweir 	        rasterconvertB3DArea(nStartLine, nStopLine);
321cdf0e10cSrcweir         }
322cdf0e10cSrcweir     }
323cdf0e10cSrcweir 
324cdf0e10cSrcweir     void RasterConverter3D::rasterconvertB3DPolyPolygon(const B3DPolyPolygon& rFill, const B3DHomMatrix* pViewToEye, sal_Int32 nStartLine, sal_Int32 nStopLine)
325cdf0e10cSrcweir     {
326cdf0e10cSrcweir 	    reset();
327cdf0e10cSrcweir 	    maLineEntries.clear();
328cdf0e10cSrcweir 	    addArea(rFill, pViewToEye);
329cdf0e10cSrcweir 	    rasterconvertB3DArea(nStartLine, nStopLine);
330cdf0e10cSrcweir     }
331cdf0e10cSrcweir 
332cdf0e10cSrcweir     void RasterConverter3D::rasterconvertB3DPolygon(const B3DPolygon& rLine, sal_Int32 nStartLine, sal_Int32 nStopLine, sal_uInt16 nLineWidth)
333cdf0e10cSrcweir     {
334cdf0e10cSrcweir 	    const sal_uInt32 nPointCount(rLine.count());
335cdf0e10cSrcweir 
336cdf0e10cSrcweir 	    if(nPointCount)
337cdf0e10cSrcweir 	    {
338cdf0e10cSrcweir 		    const sal_uInt32 nEdgeCount(rLine.isClosed() ? nPointCount : nPointCount - 1);
339cdf0e10cSrcweir 
340cdf0e10cSrcweir 		    for(sal_uInt32 a(0); a < nEdgeCount; a++)
341cdf0e10cSrcweir 		    {
342cdf0e10cSrcweir 			    rasterconvertB3DEdge(rLine, a, (a + 1) % nPointCount, nStartLine, nStopLine, nLineWidth);
343cdf0e10cSrcweir 		    }
344cdf0e10cSrcweir 	    }
345cdf0e10cSrcweir     }
346cdf0e10cSrcweir } // end of namespace basegfx
347cdf0e10cSrcweir 
348cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
349cdf0e10cSrcweir // eof
350