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