--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/svgtopt/gfx2d/src/GfxRenderer/GfxEdgeListP.cpp Thu Jan 07 16:19:02 2010 +0200
@@ -0,0 +1,848 @@
+/*
+* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Graphics Extension Library source file
+*
+*/
+
+
+#include "GfxRendererInfoP.h"
+
+#define EInitialised 0
+#define ECurrent 1
+#define EComplete 2
+
+
+// ---------------------------------------------------------------------------
+// Create a new instance and push it onto the cleanup stack.
+// ---------------------------------------------------------------------------
+// --------------------------------------------------------------------------
+// CGfxEdgeListP* CGfxEdgeListP::NewLC( TGfxRendererInfoP* aRenderInfo )
+// ---------------------------------------------------------------------------
+CGfxEdgeListP* CGfxEdgeListP::NewLC( TGfxRendererInfoP* aRenderInfo )
+ {
+ CGfxEdgeListP* self = new ( ELeave ) CGfxEdgeListP( aRenderInfo );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// Create a new instance.
+// ---------------------------------------------------------------------------
+// --------------------------------------------------------------------------
+// CGfxEdgeListP* CGfxEdgeListP::NewL( TGfxRendererInfoP* aRenderInfo )
+// ---------------------------------------------------------------------------
+CGfxEdgeListP* CGfxEdgeListP::NewL( TGfxRendererInfoP* aRenderInfo )
+ {
+ CGfxEdgeListP* self = NewLC( aRenderInfo );
+ CleanupStack::Pop();
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// Destructor.
+// ---------------------------------------------------------------------------
+// --------------------------------------------------------------------------
+// CGfxEdgeListP::~CGfxEdgeListP()
+// ---------------------------------------------------------------------------
+CGfxEdgeListP::~CGfxEdgeListP()
+ {
+ delete[] iPoints;
+ iPoints = NULL;
+ delete[] iSegset;
+ iSegset = NULL;
+ delete[] iEdges;
+ iEdges = NULL;
+ }
+
+// ---------------------------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------------------------
+// --------------------------------------------------------------------------
+// CGfxEdgeListP::CGfxEdgeListP( TGfxRendererInfoP* aRenderInfo ) : iWaitingSegList( NULL ),
+// ---------------------------------------------------------------------------
+CGfxEdgeListP::CGfxEdgeListP( TGfxRendererInfoP* aRenderInfo ) : iWaitingSegList( NULL ),
+ iActiveSegList( NULL ),
+ iPointsCount( 0 ),
+ iSegsetCount( 0 ),
+ iPointsCountMax( 20 ),
+ iSegsetCountMax( 10 ),
+ iEdgesCountMax( 10 )
+ {
+ // From CGfxEdgeListP
+ iRenderInfo = aRenderInfo;
+ iMinX = KMAXFLOATFIX;
+ iMinY = KMAXFLOATFIX;
+ iMaxX = KMINFLOATFIX;
+ iMaxY = KMINFLOATFIX;
+ iEdgesCount = 0;
+ iLastSegLenSq = 0xffffffff;
+ }
+
+// ---------------------------------------------------------------------------
+// Second phase in constructing this object.
+// ---------------------------------------------------------------------------
+// --------------------------------------------------------------------------
+// void CGfxEdgeListP::ConstructL()
+// ---------------------------------------------------------------------------
+void CGfxEdgeListP::ConstructL()
+ {
+ iPoints = new ( ELeave ) TPoint16[iPointsCountMax];
+ iSegset = new ( ELeave ) TSegSet[iSegsetCountMax];
+ iEdges = new ( ELeave ) TGfxSegEdge[iEdgesCountMax];
+ }
+
+
+// ---------------------------------------------------------------------------
+// reset
+// ---------------------------------------------------------------------------
+// --------------------------------------------------------------------------
+// void CGfxEdgeListP::Reset()
+// ---------------------------------------------------------------------------
+void CGfxEdgeListP::Reset()
+ {
+ // From CGfxEdgeListP
+ iEdgesCount = 0;
+ iLastSegLenSq = 0xffffffff;
+ iPolygonAreaSize = 0;
+ iMinX = KMAXFLOATFIX;
+ iMinY = KMAXFLOATFIX;
+ iMaxX = KMINFLOATFIX;
+ iMaxY = KMINFLOATFIX;
+
+ iPointsCount = 0;
+ iSegsetCount = 0;
+
+ iActiveSegList = 0;
+ iWaitingSegList = 0;
+ iSortedEdges = 0;
+
+ iStartSeg = iSegset;
+ iIsNewOutlineStarted = EFalse;
+ iSubPathSegmentCount = 0;
+ }
+
+// --------------------------------------------------------------------------
+// void CGfxEdgeListP::AdjustShapeComplexityL( TInt32 aVertexSize )
+// ---------------------------------------------------------------------------
+void CGfxEdgeListP::AdjustShapeComplexityL( TInt32 aVertexSize )
+ {
+ if ( aVertexSize < iPointsCountMax )
+ return;
+ //
+ delete[] iPoints;
+ delete[] iSegset;
+ delete[] iEdges;
+ iPoints = NULL;
+ iSegset = NULL;
+ iEdges = NULL;
+ iPointsCountMax = aVertexSize + 4;
+ iSegsetCountMax = aVertexSize;
+ iEdgesCountMax = aVertexSize;
+ iPoints = new ( ELeave ) TPoint16[iPointsCountMax];
+ iSegset = new ( ELeave ) TSegSet[iSegsetCountMax];
+ iEdges = new ( ELeave ) TGfxSegEdge[iEdgesCountMax];
+ }
+
+// --------------------------------------------------------------------------
+// void CGfxEdgeListP::StartPoint( TFixPt& aX, TFixPt& aY )
+// ---------------------------------------------------------------------------
+void CGfxEdgeListP::StartPoint( TFixPt& aX, TFixPt& aY )
+ {
+ if ( iPointsCount >= iPointsCountMax - 1 ) // No more segments?
+ return;
+
+ // New segment set. Add one point and set flag
+ TPoint16& p1 = iPoints[iPointsCount++];
+ p1.iX = ( TInt16 ) ( TInt ) aX;
+ p1.iY = ( TInt16 ) ( TInt ) aY;
+
+ // Min/Max update
+ if ( p1.iY < iMinY )
+ iMinY = p1.iY;
+ else if ( p1.iY > iMaxY )
+ iMaxY = p1.iY;
+ if ( p1.iX < iMinX )
+ iMinX = p1.iX;
+ else if ( p1.iX > iMaxX )
+ iMaxX = p1.iX;
+
+ iIsNewOutlineStarted = ETrue;
+ iSubPathSegmentCount = 0;
+ }
+
+// --------------------------------------------------------------------------
+// void CGfxEdgeListP::AddPoint( TFixPt& aX, TFixPt& aY, TBool aFillOnly, TBool aClosePath )
+// ---------------------------------------------------------------------------
+void CGfxEdgeListP::AddPoint( TFixPt& aX, TFixPt& aY, TBool aFillOnly, TBool aClosePath )
+ {
+ if ( iPointsCount >= iPointsCountMax - 1 ) // No more segments?
+ return;
+
+ TBool newSegsetFlag = EFalse;
+ TBool completeSubPathFlag = EFalse;
+
+ if ( iIsNewOutlineStarted )
+ {
+ CheckAndConnect();
+ newSegsetFlag = ETrue;
+ }
+ else if ( aClosePath && ( iSubPathSegmentCount == 1 ) )
+ {
+ completeSubPathFlag = ETrue;
+ newSegsetFlag = ETrue;
+ }
+ else
+ {
+ TInt x = ( TInt ) aX, y = ( TInt ) aY;
+ switch ( iSegset[iSegsetCount - 1].AddSegment( x,
+ y,
+ iLastSegLenSq,
+ aClosePath ) )
+ {
+ case ESegAdd:
+ // Add point
+ iPointsCount++;
+ break;
+ case ESegMerge:
+ // Do nothing
+ break;
+ case ESegStartNew:
+ newSegsetFlag = ETrue;
+ break;
+ default:
+ return;// ESegIgnore - do nothing
+ }
+ }
+
+ if ( newSegsetFlag && iSegsetCount < iSegsetCountMax )
+ {
+ // New segment set. Add two points
+ TPoint16* p =& iPoints[iPointsCount++];
+ p->iX = ( TInt16 ) ( TInt ) aX;
+ p->iY = ( TInt16 ) ( TInt ) aY;
+
+ iSubPathSegmentCount++;
+ TSegSet& seg = iSegset[iSegsetCount++];
+ seg.Construct( p - 1, p );
+
+ if ( iSegsetCount > 1 )
+ iSegset[iSegsetCount - 2].iNext = &seg;
+
+ if ( iIsNewOutlineStarted )
+ iStartSeg = &seg;
+
+ if ( completeSubPathFlag ) // (cdm)
+ {
+ iSegset[iSegsetCount - 1].iSign = -1;
+ iSegset[iSegsetCount - 2].iSign = 1;
+ iSegset[iSegsetCount - 1].iConnectFlag = EFalse;
+ iSegset[iSegsetCount - 2].iConnectFlag = EFalse;
+ }
+ }
+
+ // Min/Max update
+ TPoint16& p = iPoints[iPointsCount - 1];
+ if ( p.iY < iMinY )
+ iMinY = p.iY;
+ else if ( p.iY > iMaxY )
+ iMaxY = p.iY;
+ if ( p.iX < iMinX )
+ iMinX = p.iX;
+ else if ( p.iX > iMaxX )
+ iMaxX = p.iX;
+
+ if ( aFillOnly )
+ {
+ iSegset[iSegsetCount - 1].iFillOnlySeg = &iPoints[iPointsCount - 1];
+ }
+
+ iIsNewOutlineStarted = EFalse;
+ }
+
+// --------------------------------------------------------------------------
+// void CGfxEdgeListP::SetupEdgeList()
+// ---------------------------------------------------------------------------
+void CGfxEdgeListP::SetupEdgeList()
+ {
+ TInt i;
+
+ //
+ CheckAndConnect();
+
+ // Sort waiting list
+ TSegSet* segset = iSegset;
+ for ( i = 0; i < iSegsetCount; i++ )
+ {
+ if ( segset->iValid )
+ {
+ InsertToList( ETrue, * segset );
+ if ( segset->iActualBottomY < 0 )
+ segset->iActualBottomY = segset->iBottomPoint->iY;
+ }
+ segset++;
+ }
+
+ // Normalize x coordinates
+ for ( i = 0; i < iPointsCount; i++ )
+ {
+ iPoints[i].iX = ( TInt16 ) ( iPoints[i].iX - iMinX );
+ }
+
+ // Setting up for simple polygon, if applicable
+ if ( iSegsetCount < 4 )
+ {
+ TInt ix = 0;
+ segset = iWaitingSegList;
+
+ iSegListForSimple[0] = iSegListForSimple[1] = NULL; // (cdm).
+
+ while ( segset )
+ {
+ if ( segset->iTopPoint->iY <= iMinY )
+ {
+ iSegListForSimple[ix++] = segset;
+ segset->InitDDA();
+ if ( ix > 2 )
+ break;
+ }
+ segset = segset->iNext;
+ }
+ }
+
+ }
+
+// --------------------------------------------------------------------------
+// void CGfxEdgeListP::UpdateActiveEdge( TInt aY )
+// ---------------------------------------------------------------------------
+void CGfxEdgeListP::UpdateActiveEdge( TInt aY )
+ {
+ // if number of segment is less than 4, it means the polygon is
+ // a simple polygon, which we can reduce some processing.
+ if ( iSegsetCount < 4 )
+ {
+ UpdateActiveEdgeSimple( aY );
+ return;
+ }
+
+ // Remove from active segment list
+ while ( iActiveSegList )
+ {
+ if ( aY <= iActiveSegList->iActualBottomY )
+ break;
+
+
+ iActiveSegList = iActiveSegList->iNext;
+ }
+
+ // Add newly activated segment to active segment list
+ while ( iWaitingSegList )
+ {
+ if ( aY < iWaitingSegList->iTopPoint->iY )
+ break;
+ TSegSet* seg = iWaitingSegList;
+ iWaitingSegList = iWaitingSegList->iNext;
+
+ InsertToList( EFalse, * seg ); // add to active list
+
+ seg->InitDDA();
+ }
+
+ // Add edges from active segements
+ TSegSet* asl = iActiveSegList;
+ TGfxSegEdge* edge;
+ TInt x1, x2;
+ TBool fillOnly;
+
+ iSortedEdges = 0;
+ iEdgesCount = 0;
+ while ( asl )
+ {
+ fillOnly = asl->GetEdge( x1, x2 );
+ edge = AddEdge( x1, x2 );
+ if ( !edge ) // no more edges can be added.
+ return;
+ edge->iSign = ( TInt16 ) asl->iSign;
+ edge->iOnlyForFill = ( TInt16 ) fillOnly;
+
+ asl = asl->iNext;
+ }
+ }
+
+// --------------------------------------------------------------------------
+// TGfxSegEdge* CGfxEdgeListP::EdgeList()
+// ---------------------------------------------------------------------------
+TGfxSegEdge* CGfxEdgeListP::EdgeList()
+ {
+ return iSortedEdges;
+ }
+
+// --------------------------------------------------------------------------
+// void CGfxEdgeListP::UpdateActiveEdgeSimple( TInt aY ) // (cdm)
+// ---------------------------------------------------------------------------
+void CGfxEdgeListP::UpdateActiveEdgeSimple( TInt aY ) // (cdm)
+ {
+ // Add edges from active segments
+ TGfxSegEdge* edge;
+ TInt x01, x02, x11, x12;
+ TBool fillOnly0, fillOnly1;
+ iEdgesCount = 0;
+
+ if ( iSegListForSimple[0] && iSegListForSimple[1] )
+ {
+
+ if ( aY > iSegListForSimple[0]->iActualBottomY ) // (cdm)
+ iSegListForSimple[0] = iSegListForSimple[0]->iNext;
+
+ if ( aY > iSegListForSimple[1]->iActualBottomY )
+ iSegListForSimple[1] = iSegListForSimple[1]->iNext;
+
+ if ( !iSegListForSimple[0] || !iSegListForSimple[1] )
+ return;
+
+ iEdgesCount = 2;
+ fillOnly0 = iSegListForSimple[0]->GetEdge( x01, x02 );
+ fillOnly1 = iSegListForSimple[1]->GetEdge( x11, x12 );
+
+ if ( x01 < x11 )
+ {
+ // iSegListForSimple[0] is left
+ iSortedEdges = iEdges;
+ edge = iSortedEdges;
+ edge->iStart = ( TInt16 ) x01;
+ edge->iEnd = ( TInt16 ) x02;
+ edge->iSign = ( TInt16 ) iSegListForSimple[0]->iSign;
+ edge->iOnlyForFill = ( TInt16 ) fillOnly0;
+ edge->iNext = iEdges + 1;
+
+ edge = edge->iNext;
+ edge->iStart = ( TInt16 ) x11;
+ edge->iEnd = ( TInt16 ) x12;
+ edge->iSign = ( TInt16 ) iSegListForSimple[1]->iSign;
+ edge->iOnlyForFill = ( TInt16 ) fillOnly1;
+ edge->iNext = NULL;
+ }
+ else
+ {
+ // iSegListForSimple[1] is left
+ iSortedEdges = iEdges;
+ edge = iSortedEdges;
+ edge->iStart = ( TInt16 ) x11;
+ edge->iEnd = ( TInt16 ) x12;
+ edge->iSign = ( TInt16 ) iSegListForSimple[1]->iSign;
+ edge->iOnlyForFill = ( TInt16 ) fillOnly1;
+ edge->iNext = iEdges + 1;
+
+ edge = edge->iNext;
+ edge->iStart = ( TInt16 ) x01;
+ edge->iEnd = ( TInt16 ) x02;
+ edge->iSign = ( TInt16 ) iSegListForSimple[0]->iSign;
+ edge->iOnlyForFill = ( TInt16 ) fillOnly0;
+ edge->iNext = NULL;
+ }
+ }
+ }
+
+// --------------------------------------------------------------------------
+// void CGfxEdgeListP::InsertToList( TBool aWaitingList, TSegSet& aSegSet )
+// ---------------------------------------------------------------------------
+void CGfxEdgeListP::InsertToList( TBool aWaitingList, TSegSet& aSegSet )
+ {
+ TSegSet** next;
+ if ( aWaitingList )
+ next = &iWaitingSegList;
+ else
+ next = &iActiveSegList;
+ if(aWaitingList)
+ {
+ while ( *next )
+ {
+ if ( ( *next )->iTopPoint->iY >= aSegSet.iTopPoint->iY )
+ break;
+ next = &( ( *next )->iNext );
+ }
+ }
+ else
+ {
+ while( *next )
+ {
+ if ( ( *next )->iActualBottomY >= aSegSet.iActualBottomY )
+ break;
+ next = &( ( *next )->iNext );
+
+ }
+ }
+ //
+ aSegSet.iNext = *next;
+ *next = &aSegSet;
+ }
+
+// --------------------------------------------------------------------------
+// TGfxSegEdge* CGfxEdgeListP::AddEdge( TInt32 aSt, TInt32 aEd )//, TInt aSegSign)
+// ---------------------------------------------------------------------------
+TGfxSegEdge* CGfxEdgeListP::AddEdge( TInt32 aSt, TInt32 aEd )//, TInt aSegSign)
+{
+ if ( iEdgesCount >= iEdgesCountMax - 1 ) // No more edges?
+ return NULL;
+
+ TGfxSegEdge& newEdge = iEdges[iEdgesCount++];
+ newEdge.iStart = ( TInt16 ) aSt;
+ newEdge.iEnd = ( TInt16 ) aEd;
+
+ // Insert this edge in sorted link list
+ TGfxSegEdge** next;
+ next = &iSortedEdges;
+ TInt16 lastEnd = KMINFLOATFIX;
+ while ( *next )
+ {
+ if ( newEdge.iStart < ( *next )->iStart ) // (cdm).
+ break;
+
+ lastEnd = ( *next )->iEnd;
+ next = &( ( *next )->iNext );
+ }
+ //
+ newEdge.iNext = *next;
+ *next = &newEdge;
+
+ return &newEdge;
+ }
+
+// --------------------------------------------------------------------------
+// void CGfxEdgeListP::CheckAndConnect()
+// ---------------------------------------------------------------------------
+void CGfxEdgeListP::CheckAndConnect()
+ {
+ if ( iSegsetCount < 3 ) // (cdm)
+ return;
+
+ // Merge the first one and the last one if they have same sign
+ TSegSet* lastSegset =& iSegset[iSegsetCount - 1];
+ TPoint16* ps1 = iStartSeg->iTopPoint;
+ TPoint16* ps2 = iStartSeg->iBottomPoint;
+ TPoint16* pl1 = lastSegset->iTopPoint;
+ TPoint16* pl2 = lastSegset->iBottomPoint;
+
+ if ( iStartSeg->iPointAryInc == lastSegset->iPointAryInc &&
+ iStartSeg->iConnectFlag &&
+ ( ( ps1->iX == pl1->iX && ps1->iY == pl1->iY ) ||
+ ( ps1->iX == pl2->iX && ps1->iY == pl2->iY ) ||
+ ( ps2->iX == pl1->iX && ps2->iY == pl1->iY ) ||
+ ( ps2->iX == pl2->iX && ps2->iY == pl2->iY ) ) )
+ {
+ if ( iStartSeg->iPointAryInc == 1 )
+ {
+ iStartSeg->iValid = EFalse;
+ lastSegset->iConnect = iStartSeg;
+ lastSegset->iActualBottomY = iStartSeg->iBottomPoint->iY;
+ }
+ else
+ {
+ lastSegset->iValid = EFalse;
+ iStartSeg->iConnect = lastSegset;
+ iStartSeg->iActualBottomY = lastSegset->iBottomPoint->iY;
+ }
+ }
+ }
+
+void TSegSet::Construct( TPoint16* aP1, TPoint16* aP2 )
+ {
+ if ( aP1->iY < aP2->iY )
+ {
+ iTopPoint = aP1;
+ iBottomPoint = aP2;
+ iSign = 1;
+ iPointAryInc = 1;
+ }
+ else if ( aP1->iY == aP2->iY )
+ {
+ iTopPoint = aP1;
+ iBottomPoint = aP2;
+ iSign = 0;
+ iPointAryInc = 1;
+ }
+ else
+ {
+ iTopPoint = aP2;
+ iBottomPoint = aP1;
+ iSign = -1;
+ iPointAryInc = -1;
+ }
+
+ iNext = NULL;
+ iConnect = NULL;
+ iValid = ETrue;
+ iActualBottomY = KMINFLOATFIX;
+ iFillOnlySeg = NULL;
+ iConnectFlag = ETrue;
+ }
+
+TAddSegStatus TSegSet::AddSegment( TInt aX,
+ TInt aY,
+ TUint& aLastSegLenSq,
+ TBool aClosePath )
+ {
+ TPoint16* p; // the last vertex in the array of vertex
+ if ( iPointAryInc == 1 )
+ p = iBottomPoint;
+ else
+ p = iTopPoint;
+
+ // Check sign of y diff
+ TInt16 x3 = ( TInt16 ) aX, y3 = ( TInt16 ) aY;
+
+ if ( p->iX == x3 && p->iY == y3 )
+ return ESegIgnore;
+
+ TInt sign;
+ if ( p->iY < y3 )
+ sign = 1;
+ else if ( p->iY == y3 )
+ sign = 0;
+ else
+ sign = -1;
+ if ( iSign == 0 )
+ {
+ iSign = ( TInt16 ) sign;
+ if ( sign == -1 )
+ {
+ // swap top point and bottom point
+ TPoint16* tmp = iTopPoint;
+ iTopPoint = iBottomPoint;
+ iBottomPoint = tmp;
+ iPointAryInc = -1;
+ }
+ }
+ else if ( sign != 0 && iSign != sign )
+ return ESegStartNew; // sign is different. start new segment
+
+ // Vertex merging
+ TUint lenSq = ( p->iX - x3 ) * ( p->iX - x3 ) +
+ ( p->iY - y3 ) * ( p->iY - y3 );
+ if ( !aClosePath )
+ {
+ if ( aLastSegLenSq < 9 && lenSq < 9 )
+ {
+ p->iX = x3;
+ p->iY = y3;
+ TPoint16* pp = p + iPointAryInc;
+ aLastSegLenSq = ( p->iX - pp->iX ) * ( p->iX - pp->iX ) +
+ ( p->iY - pp->iY ) * ( p->iY - pp->iY );
+ return ESegMerge;
+ }
+ }
+ aLastSegLenSq = lenSq;
+
+
+ // Add point
+ TPoint16* nextp;
+ if ( iPointAryInc == 1 )
+ nextp = ++iBottomPoint;
+ else
+ nextp = ++iTopPoint;
+ nextp->iX = x3;
+ nextp->iY = y3;
+
+ return ESegAdd;
+ }
+
+TBool TSegSet::GetEdge( TInt& aX1, TInt& aX2 )
+ {
+ TPoint16 p1, p2;
+ TBool fillOnly;
+ TBool done = SingleScanline( p1, p2 );
+
+ if ( p1.iX < p2.iX )
+ {
+ aX1 = p1.iX;
+ aX2 = p2.iX;
+ }
+ else
+ {
+ aX1 = p2.iX;
+ aX2 = p1.iX;
+ }
+
+ if ( done ) // if done, construct new DDA with next segment
+ {
+ do
+ {
+ fillOnly = ( ( iTopPoint += iPointAryInc ) == iFillOnlySeg ); // (cdm)
+
+ if ( iTopPoint == iBottomPoint )
+ {
+ if ( iConnect )
+ {
+ iTopPoint = iConnect->iTopPoint;
+ iBottomPoint = iConnect->iBottomPoint;
+ iFillOnlySeg = iConnect->iFillOnlySeg;
+ iConnect = NULL;
+ }
+ else
+ {
+ return fillOnly;
+ }
+ }
+ ConstructDDA( iTopPoint, iTopPoint + iPointAryInc );
+
+ done = SingleScanline( p1, p2 );
+
+ if ( p1.iX < p2.iX ) // update edge minX & maxX
+ {
+ if ( p1.iX < aX1 )
+ aX1 = p1.iX;
+ if ( aX2 < p2.iX )
+ aX2 = p2.iX;
+ }
+ else
+ {
+ if ( p2.iX < aX1 )
+ aX1 = p2.iX;
+ if ( aX2 < p1.iX )
+ aX2 = p1.iX;
+ }
+ }
+ while ( done );
+ }
+ else
+ {
+ fillOnly = ( iTopPoint == iFillOnlySeg || iTopPoint + iPointAryInc == iFillOnlySeg );
+ }
+ return fillOnly;
+ }
+
+void TSegSet::InitDDA()
+ {
+ ConstructDDA( iTopPoint, iTopPoint + iPointAryInc );
+ }
+
+// ---------------------------------------------------------------------------
+// DDA functions, which is mostly from Symbian's TLinearDDA
+// ---------------------------------------------------------------------------
+void TSegSet::ConstructDDA( TPoint16* aStart, TPoint16* aFinish )
+ {
+ iStart = aStart;
+ iFinish = aFinish;
+ iDifference.iWidth = ( TInt16 ) Abs( iStart->iX - iFinish->iX );
+ iDifference.iHeight = ( TInt16 ) Abs( iStart->iY - iFinish->iY );
+ iInc.iX = ( TInt16 ) ( ( iStart->iX > iFinish->iX ) ? -1 : 1 );
+ iInc.iY = ( TInt16 ) ( ( iStart->iY > iFinish->iY ) ? -1 : 1 );
+ if ( iDifference.iWidth )
+ {
+ iGradient = ( TInt16 )
+ ( ( iFinish->iY - iStart->iY ) /
+ ( iFinish->iX - iStart->iX ) );
+ }
+ else
+ {
+ iGradient = 0; // (cdm)
+ }
+
+ iPos = *iStart;
+ if ( !iGradient )
+ {
+ iCount = iDifference.iWidth;
+ }
+ else
+ {
+ iCount = iDifference.iHeight;
+ }
+ iCount >>= 1;
+ iStatus = EInitialised;
+ if ( aStart == aFinish )
+ iStatus = EComplete;
+ }
+
+TBool TSegSet::SingleStep( TPoint16& aPosition )
+ {
+ if ( iStatus == ECurrent )
+ {
+ UpdatePosition();
+ aPosition = iPos;
+ if ( iPos.iX == iFinish->iX && iPos.iY == iFinish->iY )
+ {
+ iStatus = EComplete;
+ return( ETrue );
+ }
+ return( EFalse );
+ }
+ else if ( iStatus == EInitialised )
+ {
+ aPosition = *iStart;
+ iStatus = ECurrent;
+ return( EFalse );
+ }
+ else
+ {
+ aPosition = *iFinish;
+ return( ETrue );
+ };
+ }
+
+TBool TSegSet::SingleScanline( TPoint16& aStartPosition,
+ TPoint16& aEndPosition )
+ {
+ TBool done = EFalse;
+ if ( iDifference.iHeight == 0 )
+ {
+ aStartPosition = *iStart;
+ aEndPosition = *iFinish;
+ iStatus = EComplete; //KM
+ return( ETrue );
+ }
+ if ( iDifference.iWidth == 0 || iGradient )
+ {
+ done = SingleStep( aStartPosition );
+ aEndPosition = aStartPosition;
+ return( done );
+ }
+ done = SingleStep( aStartPosition );
+ aEndPosition = aStartPosition;
+ while ( iCount - iDifference.iHeight >= 0 && !done )
+ {
+ done = SingleStep( aEndPosition );
+ }
+ return( done );
+ }
+
+void TSegSet::UpdatePosition()
+ {
+ if ( iDifference.iHeight == 0 ) // horizontal line
+ iPos.iX = ( TInt16 ) ( iPos.iX + iInc.iX );
+ else if ( iDifference.iWidth == 0 ) // vertical line
+ iPos.iY = ( TInt16 ) ( iPos.iY + iInc.iY );
+ else
+ {
+ if ( !iGradient )
+ {
+ iCount = ( TInt16 ) ( iCount - iDifference.iHeight );
+ if ( iCount < 0 )
+ {
+ iCount = ( TInt16 ) ( iCount + iDifference.iWidth );
+ iPos.iY = ( TInt16 ) ( iPos.iY + iInc.iY );
+ }
+ iPos.iX = ( TInt16 ) ( iPos.iX + iInc.iX );
+ }
+ else
+ {
+ iCount = ( TInt16 ) ( iCount - iDifference.iWidth );
+ if ( iCount < 0 )
+ {
+ iCount = ( TInt16 ) ( iCount + iDifference.iHeight );
+ iPos.iX = ( TInt16 ) ( iPos.iX + iInc.iX );
+ }
+ iPos.iY = ( TInt16 ) ( iPos.iY + iInc.iY );
+ }
+ }
+ }