os/graphics/graphicsdeviceinterface/directgdiadaptation/swsrc/swdirectgdipolygon.cpp
First public contribution.
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
16 #include "swdirectgdipolygon.h"
19 A utility class used to sort vertex lists based on y coordinates.
20 @see CSwDirectGdiPolygonFiller
25 NONSHARABLE_CLASS(TCompareEdgesUpperY) : public TKey
28 TCompareEdgesUpperY(const CSwDirectGdiPolygonFiller::SFastData& aFastData);
30 virtual TInt Compare(TInt aLeft,TInt aRight) const;
32 const CSwDirectGdiPolygonFiller::SFastData& iFastData;
35 TCompareEdgesUpperY::TCompareEdgesUpperY(const CSwDirectGdiPolygonFiller::SFastData& aFastData):
41 Compare edges based on their upper Y coordinate.
43 @param aLeft Index corresponding to the "left" side of the comparison.
44 @param aRight Index corresponding to the "right" side of the comparison.
46 @return Zero, if the two keys are equal; negative, if the left key is less than the right key; positive, if the left key is greater than the right key.
50 TInt TCompareEdgesUpperY::Compare(TInt aLeft,TInt aRight) const
52 const TInt leftUpperY=iFastData.vertexList[iFastData.edgeList[aLeft].upperVertex].iY;
53 const TInt rightUpperY=iFastData.vertexList[iFastData.edgeList[aRight].upperVertex].iY;
54 if (leftUpperY<rightUpperY)
56 if (leftUpperY>rightUpperY)
62 A utility class used to swap entries in edgeList arrays during sort operations.
63 @see CSwDirectGdiPolygonFiller
68 NONSHARABLE_CLASS(TSwapEdges) : public TSwap
71 TSwapEdges(CSwDirectGdiPolygonFiller::SFastData& aFastData);
73 virtual void Swap(TInt aLeft,TInt aRight) const;
75 CSwDirectGdiPolygonFiller::SFastData& iFastData;
78 TSwapEdges::TSwapEdges(CSwDirectGdiPolygonFiller::SFastData& aFastData):
84 Swaps two elements of an edgeList array.
86 @param aLeft The index of an array element participating in the swap.
87 @param aRight The index of an array element participating in the swap.
91 void TSwapEdges::Swap(TInt aLeft,TInt aRight) const
93 CSwDirectGdiPolygonFiller::SFastEdge& leftEdge=iFastData.edgeList[aLeft];
94 CSwDirectGdiPolygonFiller::SFastEdge& rightEdge=iFastData.edgeList[aRight];
96 const CSwDirectGdiPolygonFiller::SFastEdge temp(leftEdge);
102 A utility class used to sort active edge lists based on the order of their vertexes.
103 @see CSwDirectGdiPolygonFiller
108 NONSHARABLE_CLASS(TCompareActiveEdgesFirstVertex) : public TKey
111 TCompareActiveEdgesFirstVertex(const CSwDirectGdiPolygonFiller::SFastData& aFastData);
113 virtual TInt Compare(TInt aLeft,TInt aRight) const;
115 const CSwDirectGdiPolygonFiller::SFastData& iFastData;
118 TCompareActiveEdgesFirstVertex::TCompareActiveEdgesFirstVertex(const CSwDirectGdiPolygonFiller::SFastData& aFastData):
124 Compare edges based on the order of their vertexes.
126 @param aLeft Index corresponding to the "left" side of the comparison.
127 @param aRight Index corresponding to the "right" side of the comparison.
129 @return Zero, if the two keys are equal; negative, if the left key is less than the right key; positive, if the left key is greater than the right key.
133 TInt TCompareActiveEdgesFirstVertex::Compare(TInt aLeft,TInt aRight) const
135 const TInt leftFirstVertex=iFastData.activeEdgeList[aLeft].edgePtr->firstVertex;
136 const TInt rightFirstVertex=iFastData.activeEdgeList[aRight].edgePtr->firstVertex;
137 if (leftFirstVertex<rightFirstVertex)
139 if (leftFirstVertex>rightFirstVertex)
145 A utility class used to swap entries in activeEdgeList arrays during sort operations.
146 @see CSwDirectGdiPolygonFiller
151 NONSHARABLE_CLASS(TSwapActiveEdges) : public TSwap
154 TSwapActiveEdges(CSwDirectGdiPolygonFiller::SFastData& aFastData);
156 virtual void Swap(TInt aLeft,TInt aRight) const;
158 CSwDirectGdiPolygonFiller::SFastData& iFastData;
161 TSwapActiveEdges::TSwapActiveEdges(CSwDirectGdiPolygonFiller::SFastData& aFastData):
167 Swaps two elements of an activeEdgeList array.
168 @param aLeft The index of an array element participating in the swap.
169 @param aRight The index of an array element participating in the swap.
172 void TSwapActiveEdges::Swap(TInt aLeft,TInt aRight) const
174 CSwDirectGdiPolygonFiller::SFastActiveEdge& leftActiveEdge=iFastData.activeEdgeList[aLeft];
175 CSwDirectGdiPolygonFiller::SFastActiveEdge& rightActiveEdge=iFastData.activeEdgeList[aRight];
177 const CSwDirectGdiPolygonFiller::SFastActiveEdge temp(leftActiveEdge);
178 leftActiveEdge=rightActiveEdge;
179 rightActiveEdge=temp;
181 if (leftActiveEdge.scanLineIntersectionPtr!=NULL)
182 leftActiveEdge.scanLineIntersectionPtr->activeEdgePtr=&leftActiveEdge;
183 if (rightActiveEdge.scanLineIntersectionPtr!=NULL)
184 rightActiveEdge.scanLineIntersectionPtr->activeEdgePtr=&rightActiveEdge;
188 A utility class used to sort intersection lists based on the position of their first pixel.
189 @see CSwDirectGdiPolygonFiller
194 NONSHARABLE_CLASS(TCompareScanLineIntersectionsFirstPixel) : public TKey
197 TCompareScanLineIntersectionsFirstPixel(const CSwDirectGdiPolygonFiller::SFastData& aFastData);
199 virtual TInt Compare(TInt aLeft,TInt aRight) const;
201 const CSwDirectGdiPolygonFiller::SFastData& iFastData;
204 TCompareScanLineIntersectionsFirstPixel::TCompareScanLineIntersectionsFirstPixel(const CSwDirectGdiPolygonFiller::SFastData& aFastData):
210 Compare intersections based on the order of their first pixel.
212 @param aLeft Index corresponding to the "left" side of the comparison.
213 @param aRight Index corresponding to the "right" side of the comparison.
215 @return Zero, if the two keys are equal; negative, if the left key is less than the right key; positive, if the left key is greater than the right key.
219 TInt TCompareScanLineIntersectionsFirstPixel::Compare(TInt aLeft,TInt aRight) const
221 const TInt leftFirstPixel=iFastData.scanLineIntersectionList[aLeft].firstPixel;
222 const TInt rightFirstPixel=iFastData.scanLineIntersectionList[aRight].firstPixel;
223 if (leftFirstPixel<rightFirstPixel)
225 if (leftFirstPixel>rightFirstPixel)
231 A utility class used to swap entries in intersection list arrays during sort operations.
232 @see CSwDirectGdiPolygonFiller
237 NONSHARABLE_CLASS(TSwapScanLineIntersections) : public TSwap
240 TSwapScanLineIntersections(CSwDirectGdiPolygonFiller::SFastData& aFastData);
242 virtual void Swap(TInt aLeft,TInt aRight) const;
244 CSwDirectGdiPolygonFiller::SFastData& iFastData;
247 TSwapScanLineIntersections::TSwapScanLineIntersections(CSwDirectGdiPolygonFiller::SFastData& aFastData):
253 Swaps two elements of a scanLineIntersectionList array.
254 @param aLeft The index of an array element participating in the swap.
255 @param aRight The index of an array element participating in the swap.
258 void TSwapScanLineIntersections::Swap(TInt aLeft,TInt aRight) const
260 CSwDirectGdiPolygonFiller::SFastScanLineIntersection& leftScanLineIntersection=iFastData.scanLineIntersectionList[aLeft];
261 CSwDirectGdiPolygonFiller::SFastScanLineIntersection& rightScanLineIntersection=iFastData.scanLineIntersectionList[aRight];
263 const CSwDirectGdiPolygonFiller::SFastScanLineIntersection temp(leftScanLineIntersection);
264 leftScanLineIntersection=rightScanLineIntersection;
265 rightScanLineIntersection=temp;
267 leftScanLineIntersection.activeEdgePtr->scanLineIntersectionPtr=&leftScanLineIntersection;
268 rightScanLineIntersection.activeEdgePtr->scanLineIntersectionPtr=&rightScanLineIntersection;
274 @param aCount The number of elements in the array.
275 @param aKey A reference to a suitably initialised TKey derived object.
276 @param aSwap A reference to a suitably initialised TSwap derived object.
277 @panic DGDIAdapter 1015, if QuickSort failed.
281 LOCAL_C void Sort(TInt aCount,const TKey& aKey,const TSwap& aSwap)
284 const TInt error=User::QuickSort(aCount,aKey,aSwap);
285 GRAPHICS_ASSERT_ALWAYS(error==KErrNone, EDirectGdiPanicPolygonFiller);
286 #elif 0 // bubble sort
287 for (TInt i=1; i<aCount; ++i)
289 for (TInt j=i; j>0; --j)
291 if (aKey.Compare(j-1,j)>0)
298 TInt startOfSortedPortion=aCount;
299 if (startOfSortedPortion>1)
301 TInt startOfHeap=startOfSortedPortion>>1;
304 GRAPHICS_ASSERT_DEBUG(startOfHeap>=0, EDirectGdiPanicPolygonFiller);
311 --startOfSortedPortion;
312 aSwap.Swap(startOfSortedPortion,0);
313 GRAPHICS_ASSERT_DEBUG(startOfSortedPortion>=1, EDirectGdiPanicPolygonFiller);
314 if (startOfSortedPortion==1)
319 // put aArray[startOfHeap] into the correct place in the heap
324 if ((j>=startOfSortedPortion) || (aKey.Compare(j-1,j)>0))
328 if ((j>=startOfSortedPortion) || (aKey.Compare(i,j)>=0))
340 for (TInt i=1; i<aCount; ++i)
342 GRAPHICS_ASSERT_DEBUG(aKey.Compare(i-1,i)<=0, EDirectGdiPanicPolygonFiller);
349 CSwDirectGdiPolygonFiller
353 Constructor which initialises all member data to zero, EFalse or null for
354 TInt, TBool pointers respectively.
356 CSwDirectGdiPolygonFiller::CSwDirectGdiPolygonFiller():
359 iFillRule(DirectGdi::EAlternate),
360 iUseFastAlgorithm(EFalse),
364 iScanLineIntersection(0),
365 iRightMostPixelOnScanLine(0),
367 iPolygonIsAllHorizontal(EFalse),
372 iFastData.vertexList=NULL;
373 iFastData.edgeList=NULL;
374 iFastData.activeEdgeList=NULL;
375 iFastData.scanLineIntersectionList=NULL;
376 iFastData.numActiveEdges=0;
377 iFastData.numScanLineIntersections=0;
378 iFastData.nextEdgeToActivate=0;
379 iSlowData.numIntersectionsWithSameFirstPixelPreviouslyMet=0;
380 iSlowData.numIntersectionsWithSameFirstPixelMetThisTime=0;
381 iSlowData.numScanLineIntersections=0;
382 iSlowData.scanLineComplete=EFalse;
383 iSlowData.firstPixelOfLastIntersectionInPrevBuffer=0;
387 Destructor calls reset on the polygon.
389 CSwDirectGdiPolygonFiller::~CSwDirectGdiPolygonFiller()
395 An overloaded version of Construct which allows the list of points to be passed in as a point array.
396 Exactly the same behaviour and structure as above. This should not fail. This method does not require the
397 number of nodes to be given as a parameter.
399 @param aPointArray A pointer to point array, as opposed to a pointer to a point list.
400 @param aFillRule How filling should be achieved, as described by a DirectGdi::TFillRule object.
401 @param aUsage How the polygon should be used.
402 @panic DGDIAdapter 1015, if aPointArray is NULL.
404 void CSwDirectGdiPolygonFiller::Construct(const TArray<TPoint>* aPointArray,
405 DirectGdi::TFillRule aFillRule, TUsage aUsage)
407 GRAPHICS_ASSERT_ALWAYS(aPointArray!=NULL,EDirectGdiPanicPolygonFiller);
408 iPointArray=aPointArray;
409 iNumVertexes=iPointArray->Count();
410 Construct(aFillRule,aUsage);
414 Builds up the internal meta-data needed to fill the polygon.
416 @param aFillRule How filling should be achieved, as described by a DirectGdi::TFillRule object.
417 @param aUsage How the polygon should be used, see TUsage enumeration.
418 @panic DGDIAdapter 1015, if aFillRule is invalid, or aUsage is invalid.
420 void CSwDirectGdiPolygonFiller::Construct(DirectGdi::TFillRule aFillRule, TUsage aUsage)
422 GRAPHICS_ASSERT_ALWAYS((aFillRule==DirectGdi::EAlternate) || (aFillRule==DirectGdi::EWinding),
423 EDirectGdiPanicPolygonFiller);
424 GRAPHICS_ASSERT_ALWAYS((aUsage==EGetAllPixelRunsSequentially) || (aUsage==EGetPixelRunsSequentiallyForSpecifiedScanLines),
425 EDirectGdiPanicPolygonFiller);
428 iUseFastAlgorithm=(aUsage==EGetAllPixelRunsSequentially);
431 iScanLineIntersection=0;
432 iRightMostPixelOnScanLine=KMinTInt;
433 // find the first vertex and see if the polygon is all horizontal
434 iFirstVertex=0; // dummy default value
435 iPolygonIsAllHorizontal=ETrue;
437 for (i=0; i<iNumVertexes; ++i)
438 if (Point(i).iY!=Point((i+1)%iNumVertexes).iY)
440 // i is now set to the vertex before the first non-horizontal edge
442 // set j%iNumVertexes to the vertex before the next non-horizontal edge
443 for (j=i+1; Point(j%iNumVertexes).iY==Point((j+1)%iNumVertexes).iY; ++j)
446 TInt first=Point(i).iY;
447 TInt middle=Point(j).iY;
448 TInt last=Point((j+1)%iNumVertexes).iY;
450 // if vertex j is a max or min point, set the first-vertex to be j
451 if ((middle<first)==(middle<last))
454 iPolygonIsAllHorizontal=EFalse;
459 if (iUseFastAlgorithm)
461 iFastData.vertexList=(TPoint*)User::Alloc(sizeof(TPoint)*iNumVertexes);
462 iFastData.edgeList=(SFastEdge*)User::Alloc(sizeof(SFastEdge)*iNumVertexes);
463 iFastData.activeEdgeList=(SFastActiveEdge*)User::Alloc(sizeof(SFastActiveEdge)*iNumVertexes);
464 iFastData.scanLineIntersectionList=(SFastScanLineIntersection*)User::Alloc(sizeof(SFastScanLineIntersection)*iNumVertexes);
465 if ((iFastData.vertexList==NULL) ||
466 (iFastData.edgeList==NULL) ||
467 (iFastData.activeEdgeList==NULL) ||
468 (iFastData.scanLineIntersectionList==NULL))
470 Reset(); // sets iUseFastAlgorithm to EFalse among other things
474 if (iUseFastAlgorithm)
476 for(TInt vertexcount=0;vertexcount<iNumVertexes;vertexcount++)
477 new(&iFastData.activeEdgeList[vertexcount]) SFastActiveEdge;
478 iFastData.numActiveEdges=0;
479 iFastData.numScanLineIntersections=0;
480 iFastData.nextEdgeToActivate=0;
482 // put the points into the vertex-list
483 // N.B. this array is used for speed since CArrayXxxs are slower for indexing into than built-in arrays
484 for (i=0; i<iNumVertexes; ++i)
486 // If iFastData.vertexList is NULL this will never be run. iFastData.vertexList is checked
487 // above after which iUseFastAlgorithm is set to EFalse if it is NULL (in Reset())
488 // coverity[var_deref_op]
489 iFastData.vertexList[i]=Point((i+iFirstVertex)%iNumVertexes);
493 for (i=0; i<iNumVertexes; ++i)
495 // See preceding coverity comment
496 // coverity[var_deref_op]
497 if (iFastData.vertexList[i].iY<iFastData.vertexList[(i+1)%iNumVertexes].iY)
499 iFastData.edgeList[i].upperVertex=i;
500 iFastData.edgeList[i].lowerVertex=(i+1)%iNumVertexes;
504 iFastData.edgeList[i].upperVertex=(i+1)%iNumVertexes;
505 iFastData.edgeList[i].lowerVertex=i;
507 iFastData.edgeList[i].firstVertex=i;
510 // sort edge-list into order of increasing upper y-position
511 Sort(iNumVertexes,TCompareEdgesUpperY(iFastData),TSwapEdges(iFastData));
513 // find the first scan-line
514 iFirstScanLine=iFastData.vertexList[iFastData.edgeList[0].upperVertex].iY;
516 // find the last scan-line
517 iLastScanLine=iFirstScanLine;
518 for (i=0; i<iNumVertexes; ++i)
519 if (iLastScanLine<iFastData.vertexList[i].iY)
520 iLastScanLine=iFastData.vertexList[i].iY;
524 iSlowData.numIntersectionsWithSameFirstPixelPreviouslyMet=0;
525 iSlowData.scanLineComplete=EFalse;
526 iSlowData.firstPixelOfLastIntersectionInPrevBuffer=KMinTInt;
528 // find the first and last scan-lines
529 iFirstScanLine=KMaxTInt;
530 iLastScanLine=KMinTInt;
531 for (i=0; i<iNumVertexes; ++i)
534 if (iFirstScanLine>y)
541 iCurrentScanLine=iFirstScanLine;
545 Frees any data held in the polygon’s lists of edges, vertexes and scan lines, and sets these values to NULL.
546 It also has the feature of setting iUseFastAlgorithm = EFalse.
548 void CSwDirectGdiPolygonFiller::Reset()
550 if(iUseFastAlgorithm)
552 if(iFastData.vertexList)
554 User::Free(iFastData.vertexList);
555 iFastData.vertexList=NULL;
557 if(iFastData.edgeList)
559 User::Free(iFastData.edgeList);
560 iFastData.edgeList=NULL;
562 if(iFastData.activeEdgeList)
564 User::Free(iFastData.activeEdgeList);
565 iFastData.activeEdgeList=NULL;
567 if(iFastData.scanLineIntersectionList)
569 User::Free(iFastData.scanLineIntersectionList);
570 iFastData.scanLineIntersectionList=NULL;
572 iUseFastAlgorithm=EFalse;
577 Method is used to calculate the locations of vertex interactions between the polygon and scan lines.
578 An initial scan line is required. It calculates the start and end positions on the line. The method
579 can use either the fast or slow polygon algorithm depending upon the state of aUsage. Polygon filling
580 is also addressed by this method.
582 @param aExists Will be set to EFalse if a polygon with no vertexes is passed in, otherwise ETrue on return.
583 @param aScanLine On return will contain iScanline at the beginning of the operation.
584 @param aStart On return, contains the position on the scan line to start the run.
585 @param aEnd On return, contains the position on the scan line to end the run.
586 @panic DGDIAdapter 1015 (debug only)
588 void CSwDirectGdiPolygonFiller::GetNextPixelRun(TBool& aExists, TInt& aScanLine, TInt& aStart,
591 if (iCurrentScanLine>iLastScanLine)
598 aScanLine=iCurrentScanLine;
600 if (iPolygonIsAllHorizontal)
602 // set the start after the end
609 if (iUseFastAlgorithm)
613 if (iScanLineIntersection==0)
615 // add any new edges to the active-edge-list
616 for (; (iFastData.nextEdgeToActivate<iNumVertexes) &&
617 (iFastData.vertexList[iFastData.edgeList[iFastData.nextEdgeToActivate].upperVertex].iY==iCurrentScanLine);
618 ++iFastData.numActiveEdges, ++iFastData.nextEdgeToActivate)
620 iFastData.activeEdgeList[iFastData.numActiveEdges].edgePtr=&iFastData.edgeList[iFastData.nextEdgeToActivate];
621 iFastData.activeEdgeList[iFastData.numActiveEdges].lineGenerator.Construct(
622 iFastData.vertexList[iFastData.edgeList[iFastData.nextEdgeToActivate].upperVertex],
623 iFastData.vertexList[iFastData.edgeList[iFastData.nextEdgeToActivate].lowerVertex]);
624 iFastData.activeEdgeList[iFastData.numActiveEdges].scanLineIntersectionPtr=NULL;
627 // sort the active-edge-list into order of adjacent edges (if possible)
628 Sort(iFastData.numActiveEdges,TCompareActiveEdgesFirstVertex(iFastData),TSwapActiveEdges(iFastData));
630 // find the intersection of each active-edge with the current scan-line
631 // for max/min vertex-runs (e.g. \/, \_/, \__/, etc.) add 2 intersections for each run
632 // for other vertex-runs (e.g. /----/) add 1 intersection for each run
633 for (i=0; i<iFastData.numActiveEdges; ++i)
635 // check that active-edge i is not horizontal
636 GRAPHICS_ASSERT_DEBUG(iFastData.vertexList[iFastData.activeEdgeList[i].edgePtr->upperVertex].iY!=
637 iFastData.vertexList[iFastData.activeEdgeList[i].edgePtr->lowerVertex].iY, EDirectGdiPanicPolygonFiller);
639 if (iFastData.vertexList[iFastData.activeEdgeList[i].edgePtr->upperVertex].iY==iCurrentScanLine)
640 // the scan-line is intersecting active-edge i at its upper-vertex
641 FastHandleVertexIntersection(i, EFalse);
642 else if (iFastData.vertexList[iFastData.activeEdgeList[i].edgePtr->lowerVertex].iY==iCurrentScanLine)
643 // the scan-line is intersecting active-edge i at its lower-vertex
644 FastHandleVertexIntersection(i, ETrue);
646 // the scan-line is intersecting active-edge i at neither of its vertexes
647 SetFastIntersection(iFastData.activeEdgeList[i],*iFastData.activeEdgeList[i].scanLineIntersectionPtr);
650 // N.B. iFastData.numScanLineIntersections is less than or equal to iFastData.numActiveEdges
652 // sort the intersection-list into increasing order of first-pixel
653 Sort(iFastData.numScanLineIntersections,TCompareScanLineIntersectionsFirstPixel(iFastData),TSwapScanLineIntersections(iFastData));
655 GRAPHICS_ASSERT_DEBUG(iFastData.numScanLineIntersections>=2, EDirectGdiPanicPolygonFiller);
658 // depending on the rule used, find the pixel-run
659 TBool doFill=EFalse; // dummy initialization to prevent compiler warning
660 if (iScanLineIntersection<iFastData.numScanLineIntersections-1)
664 case DirectGdi::EAlternate:
668 case DirectGdi::EWinding:
669 GRAPHICS_ASSERT_DEBUG(iFastData.vertexList[iFastData.scanLineIntersectionList[iScanLineIntersection].activeEdgePtr->edgePtr->lowerVertex].iY!=
670 iFastData.vertexList[iFastData.scanLineIntersectionList[iScanLineIntersection].activeEdgePtr->edgePtr->upperVertex].iY,
671 EDirectGdiPanicPolygonFiller);
673 if (iFastData.scanLineIntersectionList[iScanLineIntersection].activeEdgePtr->edgePtr->lowerVertex==
674 (iFastData.scanLineIntersectionList[iScanLineIntersection].activeEdgePtr->edgePtr->upperVertex+1)%iNumVertexes)
679 doFill=(iNestingLevel!=0);
685 aStart=Max(iRightMostPixelOnScanLine, iFastData.scanLineIntersectionList[iScanLineIntersection].lastPixel)+1;
686 aEnd=iFastData.scanLineIntersectionList[iScanLineIntersection+1].firstPixel-1;
690 // set the start after the end
695 if (iRightMostPixelOnScanLine<iFastData.scanLineIntersectionList[iScanLineIntersection].lastPixel)
696 iRightMostPixelOnScanLine=iFastData.scanLineIntersectionList[iScanLineIntersection].lastPixel;
697 ++iScanLineIntersection;
700 if (iScanLineIntersection==iFastData.numScanLineIntersections-1)
702 GRAPHICS_ASSERT_DEBUG(iFastData.vertexList[iFastData.scanLineIntersectionList[iScanLineIntersection].activeEdgePtr->edgePtr->lowerVertex].iY!=
703 iFastData.vertexList[iFastData.scanLineIntersectionList[iScanLineIntersection].activeEdgePtr->edgePtr->upperVertex].iY,
704 EDirectGdiPanicPolygonFiller);
708 case DirectGdi::EAlternate:
710 GRAPHICS_ASSERT_DEBUG(iToggler==0, EDirectGdiPanicPolygonFiller);
712 case DirectGdi::EWinding:
713 if (iFastData.scanLineIntersectionList[iScanLineIntersection].activeEdgePtr->edgePtr->lowerVertex==
714 (iFastData.scanLineIntersectionList[iScanLineIntersection].activeEdgePtr->edgePtr->upperVertex+1)%iNumVertexes)
718 GRAPHICS_ASSERT_DEBUG((iNumVertexes==2) || (iNestingLevel==0), EDirectGdiPanicPolygonFiller);
722 // remove any scan-line-intersections associated with old active-edges
723 for (i=0; i<iFastData.numScanLineIntersections; )
724 if (iFastData.vertexList[iFastData.scanLineIntersectionList[i].activeEdgePtr->edgePtr->lowerVertex].iY==iCurrentScanLine)
726 iFastData.scanLineIntersectionList[i].activeEdgePtr->scanLineIntersectionPtr=NULL;
728 // ripple all the entries in the scan-line-intersection-list after this one back one place
729 for (j=i+1; j<iFastData.numScanLineIntersections; ++j)
731 iFastData.scanLineIntersectionList[j-1]=iFastData.scanLineIntersectionList[j];
732 iFastData.scanLineIntersectionList[j-1].activeEdgePtr->scanLineIntersectionPtr=&iFastData.scanLineIntersectionList[j-1];
735 iFastData.scanLineIntersectionList[j-1].activeEdgePtr=NULL;
736 --iFastData.numScanLineIntersections;
741 // remove any old edges from the active-edge-list
742 for (i=0; i<iFastData.numActiveEdges; )
743 if (iFastData.vertexList[iFastData.activeEdgeList[i].edgePtr->lowerVertex].iY==iCurrentScanLine)
745 GRAPHICS_ASSERT_DEBUG(iFastData.activeEdgeList[i].scanLineIntersectionPtr==NULL, EDirectGdiPanicPolygonFiller);
747 // ripple all the entries in the active-edge-list after this one back one place
748 for (j=i+1; j<iFastData.numActiveEdges; ++j)
750 iFastData.activeEdgeList[j-1]=iFastData.activeEdgeList[j];
751 if (iFastData.activeEdgeList[j-1].scanLineIntersectionPtr)
752 iFastData.activeEdgeList[j-1].scanLineIntersectionPtr->activeEdgePtr=&iFastData.activeEdgeList[j-1];
755 iFastData.activeEdgeList[j-1].scanLineIntersectionPtr=NULL;
756 --iFastData.numActiveEdges;
762 for (i=0; i<iFastData.numActiveEdges; ++i)
764 GRAPHICS_ASSERT_DEBUG(iFastData.activeEdgeList[i].scanLineIntersectionPtr->activeEdgePtr==
765 &iFastData.activeEdgeList[i], EDirectGdiPanicPolygonFiller);
768 for (i=0; i<iFastData.numScanLineIntersections; ++i)
770 GRAPHICS_ASSERT_DEBUG(iFastData.scanLineIntersectionList[i].activeEdgePtr->scanLineIntersectionPtr==
771 &iFastData.scanLineIntersectionList[i], EDirectGdiPanicPolygonFiller);
775 iScanLineIntersection=0;
777 iRightMostPixelOnScanLine=KMinTInt;
782 GetNextPixelRunOnSpecifiedScanLine(aExists, iCurrentScanLine, aStart, aEnd);
784 GetNextPixelRunOnSpecifiedScanLine(aExists, ++iCurrentScanLine, aStart, aEnd);
789 Similar to GetNextPixelRun(aExists, aScanLine, aStart, aEnd) this method is used to draw the relevant
790 vertex intersections for a polygon but only for an individual specified scan line. The method
791 can use either the fast or slow polygon algorithm depending upon the state of aUsage.
793 @param aExists Will be set to false if the line does not pass through the polygon or if
794 a polygon with no vertexes is specified, otherwise ETrue on return.
795 @param aScanLine The scan line to be drawn on. Used to set iScanline
796 @param aStart On return, contains the position on the scan line to start the run.
797 @param aEnd The position on the scan line to end the run, returned.
798 @panic DGDIAdapter 1015, if iUseFastAlgorithm is ETrue (debug only).
800 void CSwDirectGdiPolygonFiller::GetNextPixelRunOnSpecifiedScanLine(TBool& aExists,
807 GRAPHICS_ASSERT_DEBUG(!iUseFastAlgorithm, EDirectGdiPanicPolygonFiller);
809 if (aScanLine<iCurrentScanLine || aScanLine>iLastScanLine)
816 iCurrentScanLine=aScanLine;
818 if (iPolygonIsAllHorizontal)
820 // set the start after the end
827 if (iScanLineIntersection==0)
829 iSlowData.numIntersectionsWithSameFirstPixelMetThisTime=0;
830 iSlowData.numScanLineIntersections=0;
831 iSlowData.scanLineComplete=ETrue;
833 // find the left-most iSlowData::EStoreSize number (or less) of intersections with this scan-line
834 for (i=iFirstVertex; i<iNumVertexes+iFirstVertex; ++i)
836 TPoint upper=Point(i%iNumVertexes);
837 TPoint lower=Point((i+1)%iNumVertexes);
838 if (upper.iY>lower.iY)
845 if ((iCurrentScanLine>=upper.iY) && (iCurrentScanLine<=lower.iY))
847 // check that the edge starting at vertex i%iNumVertexes is not horizontal
848 GRAPHICS_ASSERT_DEBUG(upper.iY!=lower.iY, EDirectGdiPanicPolygonFiller);
850 // step through the line-generator until the current scan-line is reached
851 TPoint startPos, endPos;
852 JumpToCurrentScanLine(iSlowData.lineGenerator, upper, lower, startPos, endPos);
854 // find the intersection start and end pixels
855 SSlowScanLineIntersection scanLineIntersection;
856 scanLineIntersection.firstPixel=Min(startPos.iX, endPos.iX);
857 scanLineIntersection.lastPixel=Max(startPos.iX, endPos.iX);
858 scanLineIntersection.firstVertexOfEdge=i%iNumVertexes;
860 // handle horizontal runs and minima/maxima
861 if (upper.iY==iCurrentScanLine)
862 SlowHandleVertexIntersection(scanLineIntersection, i, EFalse);
863 else if (lower.iY==iCurrentScanLine)
864 SlowHandleVertexIntersection(scanLineIntersection, i, ETrue);
866 // see if there have been other intersections with the same first-pixel
867 if (scanLineIntersection.firstPixel==iSlowData.firstPixelOfLastIntersectionInPrevBuffer)
868 ++iSlowData.numIntersectionsWithSameFirstPixelMetThisTime;
870 // if the intersection has not already been included in a previous buffer-load
871 if ((scanLineIntersection.firstPixel>iSlowData.firstPixelOfLastIntersectionInPrevBuffer) ||
872 ((scanLineIntersection.firstPixel==iSlowData.firstPixelOfLastIntersectionInPrevBuffer) &&
873 (iSlowData.numIntersectionsWithSameFirstPixelMetThisTime>=
874 iSlowData.numIntersectionsWithSameFirstPixelPreviouslyMet)))
876 // put the intersection in the right place in the intersection list (if there is room)
877 for (j=0; j<iSlowData.numScanLineIntersections; ++j)
878 if (scanLineIntersection.firstPixel<iSlowData.scanLineIntersectionList[j].firstPixel)
880 if (iSlowData.numScanLineIntersections<SSlowData::EStoreSize)
881 ++iSlowData.numScanLineIntersections;
883 iSlowData.scanLineComplete=EFalse;
885 for (k=iSlowData.numScanLineIntersections-1; k>j; --k)
886 iSlowData.scanLineIntersectionList[k]=iSlowData.scanLineIntersectionList[k-1];
887 iSlowData.scanLineIntersectionList[j]=scanLineIntersection;
890 if (j==iSlowData.numScanLineIntersections)
892 if (iSlowData.numScanLineIntersections<SSlowData::EStoreSize)
893 iSlowData.scanLineIntersectionList[iSlowData.numScanLineIntersections++]=scanLineIntersection;
895 iSlowData.scanLineComplete=EFalse;
901 if (!iSlowData.scanLineComplete)
903 GRAPHICS_ASSERT_DEBUG(iSlowData.numScanLineIntersections==SSlowData::EStoreSize, EDirectGdiPanicPolygonFiller);
905 if (iSlowData.firstPixelOfLastIntersectionInPrevBuffer==iSlowData.scanLineIntersectionList[SSlowData::EStoreSize-1].firstPixel)
906 iSlowData.numIntersectionsWithSameFirstPixelPreviouslyMet+=SSlowData::EStoreSize-1;
909 iSlowData.firstPixelOfLastIntersectionInPrevBuffer=iSlowData.scanLineIntersectionList[SSlowData::EStoreSize-1].firstPixel;
910 iSlowData.numIntersectionsWithSameFirstPixelPreviouslyMet=1;
911 for (i=SSlowData::EStoreSize-1; (i>0) && (iSlowData.firstPixelOfLastIntersectionInPrevBuffer==
912 iSlowData.scanLineIntersectionList[i-1].firstPixel); --i)
913 ++iSlowData.numIntersectionsWithSameFirstPixelPreviouslyMet;
918 // depending on the rule used, find the pixel-run
919 TBool doFill=EFalse; // dummy initialization to prevent compiler warning
920 if (iScanLineIntersection<iSlowData.numScanLineIntersections-1)
924 case DirectGdi::EAlternate:
928 case DirectGdi::EWinding:
929 GRAPHICS_ASSERT_DEBUG(Point(iSlowData.scanLineIntersectionList[iScanLineIntersection].firstVertexOfEdge).iY!=
930 Point((iSlowData.scanLineIntersectionList[iScanLineIntersection].firstVertexOfEdge+1)%iNumVertexes).iY,
931 EDirectGdiPanicPolygonFiller);
933 if (Point(iSlowData.scanLineIntersectionList[iScanLineIntersection].firstVertexOfEdge).iY>
934 Point((iSlowData.scanLineIntersectionList[iScanLineIntersection].firstVertexOfEdge+1)%iNumVertexes).iY)
939 doFill=(iNestingLevel!=0);
945 aStart=Max(iRightMostPixelOnScanLine, iSlowData.scanLineIntersectionList[iScanLineIntersection].lastPixel)+1;
946 aEnd=iSlowData.scanLineIntersectionList[iScanLineIntersection+1].firstPixel-1;
950 // set the start after the end
955 if (iRightMostPixelOnScanLine<iSlowData.scanLineIntersectionList[iScanLineIntersection].lastPixel)
956 iRightMostPixelOnScanLine=iSlowData.scanLineIntersectionList[iScanLineIntersection].lastPixel;
957 ++iScanLineIntersection;
960 if (iScanLineIntersection==iSlowData.numScanLineIntersections-1)
962 if (iSlowData.scanLineComplete)
964 GRAPHICS_ASSERT_DEBUG(Point(iSlowData.scanLineIntersectionList[iScanLineIntersection].firstVertexOfEdge).iY!=
965 Point((iSlowData.scanLineIntersectionList[iScanLineIntersection].firstVertexOfEdge+1)%iNumVertexes).iY,
966 EDirectGdiPanicPolygonFiller);
970 case DirectGdi::EAlternate:
972 GRAPHICS_ASSERT_DEBUG(iToggler==0, EDirectGdiPanicPolygonFiller);
974 case DirectGdi::EWinding:
975 if (Point(iSlowData.scanLineIntersectionList[iScanLineIntersection].firstVertexOfEdge).iY>
976 Point((iSlowData.scanLineIntersectionList[iScanLineIntersection].firstVertexOfEdge+1)%iNumVertexes).iY)
981 GRAPHICS_ASSERT_DEBUG((!iSlowData.scanLineComplete) || (iNumVertexes==2) || (iNestingLevel==0), EDirectGdiPanicPolygonFiller);
986 iScanLineIntersection=0;
987 if (iSlowData.scanLineComplete)
990 iRightMostPixelOnScanLine=KMinTInt;
991 iSlowData.numIntersectionsWithSameFirstPixelPreviouslyMet=0;
992 iSlowData.scanLineComplete=EFalse;
993 iSlowData.firstPixelOfLastIntersectionInPrevBuffer=KMinTInt;
999 Builds up drawing meta-data in the case where a scanline intersects the active edge at a vertex using
1002 @param aCurrentActiveEdge Index of the current active edge
1003 @param aIsLowerVertex If the vertex is the lower vertex ETrue otherwise EFalse.
1004 @panic DGDIAdapter 1015, if iUseFastAlgorithm is EFalse.
1006 @see GetNextPixelRun()
1008 void CSwDirectGdiPolygonFiller::FastHandleVertexIntersection(TInt& aCurrentActiveEdge,
1009 TBool aIsLowerVertex)
1011 GRAPHICS_ASSERT_DEBUG(iUseFastAlgorithm, EDirectGdiPanicPolygonFiller);
1013 if (iFastData.vertexList[(iFastData.activeEdgeList[aCurrentActiveEdge].edgePtr->firstVertex+1)%iNumVertexes].iY==iCurrentScanLine)
1014 // it is the second vertex of active-edge aCurrentActiveEdge that coincides with the current scan-line
1016 TInt origActiveEdge=aCurrentActiveEdge;
1017 SFastScanLineIntersection scanLineIntersection;
1018 scanLineIntersection.activeEdgePtr=NULL;
1019 SetFastIntersection(iFastData.activeEdgeList[origActiveEdge], scanLineIntersection);
1021 // walk through subsequent adjacent horizontal active-edges
1024 // exit the loop if the vertex-run *is* a maximum or a minimum
1025 const SFastEdge* tempEdgePtr=iFastData.activeEdgeList[(aCurrentActiveEdge+1)%iFastData.numActiveEdges].edgePtr;
1026 TBool isMaxOrMin = EFalse;
1028 switch(aIsLowerVertex)
1031 isMaxOrMin = (iFastData.vertexList[tempEdgePtr->lowerVertex].iY > iCurrentScanLine);
1035 isMaxOrMin = (iFastData.vertexList[tempEdgePtr->upperVertex].iY < iCurrentScanLine);
1040 // the vertex-run is a maximum or a minimum
1044 *iFastData.activeEdgeList[origActiveEdge].scanLineIntersectionPtr=scanLineIntersection;
1045 iFastData.activeEdgeList[origActiveEdge].scanLineIntersectionPtr->activeEdgePtr=&iFastData.activeEdgeList[origActiveEdge];
1049 // add an intersection
1050 iFastData.scanLineIntersectionList[iFastData.numScanLineIntersections]=scanLineIntersection;
1051 iFastData.scanLineIntersectionList[iFastData.numScanLineIntersections].activeEdgePtr=&iFastData.activeEdgeList[origActiveEdge];
1052 iFastData.activeEdgeList[origActiveEdge].scanLineIntersectionPtr=&iFastData.scanLineIntersectionList[iFastData.numScanLineIntersections];
1053 ++iFastData.numScanLineIntersections;
1058 // the active-edge is horizontal, or the vertex-run is not a maximum or a minimum
1060 ++aCurrentActiveEdge;
1061 GRAPHICS_ASSERT_DEBUG(aCurrentActiveEdge<iFastData.numActiveEdges, EDirectGdiPanicPolygonFiller);
1063 // update scanLineIntersection
1064 TPoint startPos, endPos;
1066 iFastData.activeEdgeList[aCurrentActiveEdge].lineGenerator.SingleScanline(startPos, endPos);
1067 minX=Min(startPos.iX, endPos.iX);
1068 maxX=Max(startPos.iX, endPos.iX);
1069 if (scanLineIntersection.firstPixel>minX)
1070 scanLineIntersection.firstPixel=minX;
1071 if (scanLineIntersection.lastPixel<maxX)
1072 scanLineIntersection.lastPixel=maxX;
1074 // exit the loop if the vertex-run is *not* a maximum or a minimum
1075 tempEdgePtr=iFastData.activeEdgeList[aCurrentActiveEdge].edgePtr;
1076 TBool isNeitherMaxOrMin = EFalse;
1078 switch(aIsLowerVertex)
1081 isNeitherMaxOrMin = (iFastData.vertexList[tempEdgePtr->upperVertex].iY < iCurrentScanLine);
1085 isNeitherMaxOrMin = (iFastData.vertexList[tempEdgePtr->lowerVertex].iY > iCurrentScanLine);
1089 // exit the loop if the vertex-run is *not* a maximum or a minimum
1090 if (isNeitherMaxOrMin)
1096 newActiveEdge=aCurrentActiveEdge;
1097 oldActiveEdge=origActiveEdge;
1101 newActiveEdge=origActiveEdge;
1102 oldActiveEdge=aCurrentActiveEdge;
1104 iFastData.activeEdgeList[newActiveEdge].scanLineIntersectionPtr=iFastData.activeEdgeList[oldActiveEdge].scanLineIntersectionPtr;
1105 iFastData.activeEdgeList[oldActiveEdge].scanLineIntersectionPtr=NULL;
1106 *iFastData.activeEdgeList[newActiveEdge].scanLineIntersectionPtr=scanLineIntersection;
1107 iFastData.activeEdgeList[newActiveEdge].scanLineIntersectionPtr->activeEdgePtr=&iFastData.activeEdgeList[newActiveEdge];
1113 // it is the first vertex of active-edge aCurrentActiveEdge that coincides with the current scan-line
1116 // check that the vertex we are at is a maximum or a minimum
1117 TInt previousNotLevelVertex;
1118 TInt SFastEdge::*vertex=(aIsLowerVertex)? &SFastEdge::lowerVertex: &SFastEdge::upperVertex;
1119 for (previousNotLevelVertex=iFastData.activeEdgeList[aCurrentActiveEdge].edgePtr->*vertex;
1120 iFastData.vertexList[iFastData.activeEdgeList[aCurrentActiveEdge].edgePtr->*vertex].iY==iFastData.vertexList[previousNotLevelVertex].iY;
1121 previousNotLevelVertex=(previousNotLevelVertex+iNumVertexes-1)%iNumVertexes)
1123 TInt nextNotLevelVertex=(iFastData.activeEdgeList[aCurrentActiveEdge].edgePtr->*vertex+1)%iNumVertexes;
1124 GRAPHICS_ASSERT_DEBUG((iFastData.vertexList[iFastData.activeEdgeList[aCurrentActiveEdge].edgePtr->*vertex].iY>iFastData.vertexList[previousNotLevelVertex].iY)==
1125 (iFastData.vertexList[iFastData.activeEdgeList[aCurrentActiveEdge].edgePtr->*vertex].iY>iFastData.vertexList[nextNotLevelVertex].iY),
1126 EDirectGdiPanicPolygonFiller);
1130 SetFastIntersection(iFastData.activeEdgeList[aCurrentActiveEdge],*iFastData.activeEdgeList[aCurrentActiveEdge].scanLineIntersectionPtr);
1133 // add an intersection
1134 SetFastIntersection(iFastData.activeEdgeList[aCurrentActiveEdge], iFastData.scanLineIntersectionList[iFastData.numScanLineIntersections]);
1135 iFastData.scanLineIntersectionList[iFastData.numScanLineIntersections].activeEdgePtr=&iFastData.activeEdgeList[aCurrentActiveEdge];
1136 iFastData.activeEdgeList[aCurrentActiveEdge].scanLineIntersectionPtr=&iFastData.scanLineIntersectionList[iFastData.numScanLineIntersections];
1137 ++iFastData.numScanLineIntersections;
1143 Calculates the extent of the intersection for the current active edge.
1145 @param aActiveEdge The current active edge.
1146 @param aScanLineIntersection On return, contains the intersection data.
1148 void CSwDirectGdiPolygonFiller::SetFastIntersection(SFastActiveEdge& aActiveEdge, SFastScanLineIntersection& aScanLineIntersection)
1150 GRAPHICS_ASSERT_DEBUG(iUseFastAlgorithm, EDirectGdiPanicPolygonFiller);
1152 TPoint startPos, endPos;
1154 aActiveEdge.lineGenerator.SingleScanline(startPos, endPos);
1155 aScanLineIntersection.firstPixel=Min(startPos.iX, endPos.iX);
1156 aScanLineIntersection.lastPixel=Max(startPos.iX, endPos.iX);
1160 Builds up drawing meta-data in the case where a scanline intersects the active edge at a vertex using
1163 @param aScanLineIntersection Reference to the current intersection data.
1164 @param aVertexStartingCurrentEdge Current vertex.
1165 @param aIsLowerVertex If the vertex is the lower vertex ETrue otherwise EFalse.
1166 @see GetNextPixelRunOnSpecifiedScanLine()
1168 void CSwDirectGdiPolygonFiller::SlowHandleVertexIntersection(SSlowScanLineIntersection& aScanLineIntersection,
1169 TInt& aVertexStartingCurrentEdge,
1170 TBool aIsLowerVertex)
1172 if (Point((aVertexStartingCurrentEdge+1)%iNumVertexes).iY==iCurrentScanLine)
1173 // it is the second vertex of the edge starting at vertex aVertexStartingCurrentEdge%iNumVertexes
1174 // that coincides with the current scan-line
1176 // walk through subsequent adjacent horizontal active-edges
1179 TPoint nextVertexButOne=Point((aVertexStartingCurrentEdge+2)%iNumVertexes);
1180 TBool isMaxOrMin = EFalse;
1182 switch(aIsLowerVertex)
1185 isMaxOrMin = (nextVertexButOne.iY > iCurrentScanLine);
1189 isMaxOrMin = (nextVertexButOne.iY < iCurrentScanLine);
1193 // exit the loop if the vertex-run *is* a maximum or a minimum
1199 // the edge starting at vertex aVertexStartingCurrentEdge%iNumVertexes is horizontal, or the vertex-run is not a
1200 // maximum or a minimum
1202 ++aVertexStartingCurrentEdge;
1203 GRAPHICS_ASSERT_DEBUG(aVertexStartingCurrentEdge%iNumVertexes!=iFirstVertex, EDirectGdiPanicPolygonFiller);
1205 // step through the line-generator until the current scan-line is reached
1206 TPoint upper=Point(aVertexStartingCurrentEdge%iNumVertexes);
1207 TPoint lower=nextVertexButOne;
1208 if (upper.iY>lower.iY)
1215 TPoint startPos, endPos;
1216 if (upper.iY!=lower.iY)
1217 JumpToCurrentScanLine(iSlowData.lineGenerator, upper, lower, startPos, endPos);
1220 // N.B. which is set to which doesn't matter, as long as startPos is set to either upper or lower, and endPos is set to the other
1225 // expand the intersection, if necessary
1226 TInt minX=Min(startPos.iX, endPos.iX);
1227 TInt maxX=Max(startPos.iX, endPos.iX);
1228 if (aScanLineIntersection.firstPixel>minX)
1229 aScanLineIntersection.firstPixel=minX;
1230 if (aScanLineIntersection.lastPixel<maxX)
1231 aScanLineIntersection.lastPixel=maxX;
1233 TBool isNeitherMaxOrMin = EFalse;
1235 switch(aIsLowerVertex)
1238 isNeitherMaxOrMin = (nextVertexButOne.iY < iCurrentScanLine);
1242 isNeitherMaxOrMin = (nextVertexButOne.iY > iCurrentScanLine);
1246 // exit the loop if the vertex-run is *not* a maximum or a minimum
1247 if (isNeitherMaxOrMin)
1251 aScanLineIntersection.firstVertexOfEdge=aVertexStartingCurrentEdge%iNumVertexes;
1258 // it is the first vertex of the edge starting at vertex aVertexStartingCurrentEdge%iNumVertexes
1259 // that coincides with the current scan-line
1262 // check that the vertex we are at is a maximum or a minimum
1263 TInt previousNotLevelVertex;
1264 for (previousNotLevelVertex=aVertexStartingCurrentEdge%iNumVertexes;
1265 Point(aVertexStartingCurrentEdge%iNumVertexes).iY==
1266 Point(previousNotLevelVertex).iY;
1267 previousNotLevelVertex=(previousNotLevelVertex+iNumVertexes-1)%iNumVertexes)
1269 TInt nextNotLevelVertex=(aVertexStartingCurrentEdge+1)%iNumVertexes;
1270 TInt previousY=Point(previousNotLevelVertex).iY;
1271 TInt currentY=Point(aVertexStartingCurrentEdge%iNumVertexes).iY;
1272 TInt nextY=Point(nextNotLevelVertex).iY;
1273 GRAPHICS_ASSERT_DEBUG((currentY>previousY) == (currentY>nextY), EDirectGdiPanicPolygonFiller);
1279 For a given line between two given endpoints, calculate the right and leftmost pixels of the line segment
1280 that fall on the current scanline.
1282 @param aLineGenerator Reference to class used to calculate the pixels on the line.
1283 @param aUpper The upper endpoint of the line.
1284 @param aLower The lower endpoint of the line.
1285 @param aStartPos On return, contains the position of the line's leftmost pixel on the current scanline.
1286 @param aEndPos On return, contains the position of the line's rightmost pixel on the current scanline.
1288 void CSwDirectGdiPolygonFiller::JumpToCurrentScanLine(TLinearDDA& aLineGenerator,
1289 const TPoint& aUpper,
1290 const TPoint& aLower,
1292 TPoint& aEndPos) const
1294 GRAPHICS_ASSERT_DEBUG(aUpper.iY<=aLower.iY, EDirectGdiPanicPolygonFiller);
1295 aLineGenerator.Construct(aUpper, aLower);
1296 if (aUpper.iY<iCurrentScanLine)
1299 aLineGenerator.JumpToYCoord(notUsed, iCurrentScanLine-2);
1302 aLineGenerator.SingleScanline(aStartPos, aEndPos);
1303 while (aStartPos.iY!=iCurrentScanLine);
1304 GRAPHICS_ASSERT_DEBUG(aStartPos.iY==iCurrentScanLine, EDirectGdiPanicPolygonFiller);
1305 GRAPHICS_ASSERT_DEBUG(aEndPos.iY==iCurrentScanLine, EDirectGdiPanicPolygonFiller);
1309 Returns the point data for a given index.
1311 @param aIndex The index.
1312 @return The point data.
1314 const TPoint& CSwDirectGdiPolygonFiller::Point(TInt aIndex)
1316 GRAPHICS_ASSERT_DEBUG(iPointArray,EDirectGdiPanicPolygonFiller);
1317 return((*iPointArray)[aIndex]);