svgtopt/gfx2d/src/GfxRenderer/GfxEdgeListP.cpp
changeset 0 d46562c3d99d
--- /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 );
+            }
+        }
+    }