svgtopt/gfx2d/src/GfxRenderer/GfxEdgeListP.cpp
changeset 0 d46562c3d99d
equal deleted inserted replaced
-1:000000000000 0:d46562c3d99d
       
     1 /*
       
     2 * Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Graphics Extension Library source file
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "GfxRendererInfoP.h"
       
    20 
       
    21 #define EInitialised  0
       
    22 #define ECurrent      1
       
    23 #define EComplete     2
       
    24 
       
    25 
       
    26 // ---------------------------------------------------------------------------
       
    27 // Create a new instance and push it onto the cleanup stack.
       
    28 // ---------------------------------------------------------------------------
       
    29 // --------------------------------------------------------------------------
       
    30 // CGfxEdgeListP* CGfxEdgeListP::NewLC( TGfxRendererInfoP* aRenderInfo )
       
    31 // ---------------------------------------------------------------------------
       
    32 CGfxEdgeListP* CGfxEdgeListP::NewLC( TGfxRendererInfoP* aRenderInfo )
       
    33     {
       
    34     CGfxEdgeListP* self = new ( ELeave ) CGfxEdgeListP( aRenderInfo );
       
    35     CleanupStack::PushL( self );
       
    36     self->ConstructL();
       
    37     return self;
       
    38     }
       
    39 
       
    40 // ---------------------------------------------------------------------------
       
    41 // Create a new instance.
       
    42 // ---------------------------------------------------------------------------
       
    43 // --------------------------------------------------------------------------
       
    44 // CGfxEdgeListP* CGfxEdgeListP::NewL( TGfxRendererInfoP* aRenderInfo )
       
    45 // ---------------------------------------------------------------------------
       
    46 CGfxEdgeListP* CGfxEdgeListP::NewL( TGfxRendererInfoP* aRenderInfo )
       
    47     {
       
    48     CGfxEdgeListP* self = NewLC( aRenderInfo );
       
    49     CleanupStack::Pop();
       
    50     return self;
       
    51     }
       
    52 
       
    53 // ---------------------------------------------------------------------------
       
    54 // Destructor.
       
    55 // ---------------------------------------------------------------------------
       
    56 // --------------------------------------------------------------------------
       
    57 // CGfxEdgeListP::~CGfxEdgeListP()
       
    58 // ---------------------------------------------------------------------------
       
    59 CGfxEdgeListP::~CGfxEdgeListP()
       
    60     {
       
    61      delete[] iPoints;
       
    62      iPoints = NULL;
       
    63      delete[] iSegset;
       
    64      iSegset = NULL;
       
    65      delete[] iEdges;
       
    66      iEdges = NULL;
       
    67     }
       
    68 
       
    69 // ---------------------------------------------------------------------------
       
    70 // Constructor
       
    71 // ---------------------------------------------------------------------------
       
    72 // --------------------------------------------------------------------------
       
    73 // CGfxEdgeListP::CGfxEdgeListP( TGfxRendererInfoP* aRenderInfo ) : iWaitingSegList( NULL ),
       
    74 // ---------------------------------------------------------------------------
       
    75 CGfxEdgeListP::CGfxEdgeListP( TGfxRendererInfoP* aRenderInfo ) : iWaitingSegList( NULL ),
       
    76                                                                  iActiveSegList( NULL ),
       
    77                                                                  iPointsCount( 0 ),
       
    78                                                                  iSegsetCount( 0 ),
       
    79 																 iPointsCountMax( 20 ),
       
    80                                                                  iSegsetCountMax( 10 ),
       
    81                                                                  iEdgesCountMax( 10 )
       
    82     {
       
    83     // From CGfxEdgeListP
       
    84     iRenderInfo = aRenderInfo;
       
    85     iMinX = KMAXFLOATFIX;
       
    86     iMinY = KMAXFLOATFIX;
       
    87     iMaxX = KMINFLOATFIX;
       
    88     iMaxY = KMINFLOATFIX;
       
    89     iEdgesCount = 0;
       
    90     iLastSegLenSq = 0xffffffff;
       
    91     }
       
    92 
       
    93 // ---------------------------------------------------------------------------
       
    94 // Second phase in constructing this object.
       
    95 // ---------------------------------------------------------------------------
       
    96 // --------------------------------------------------------------------------
       
    97 // void CGfxEdgeListP::ConstructL()
       
    98 // ---------------------------------------------------------------------------
       
    99 void CGfxEdgeListP::ConstructL()
       
   100     {
       
   101     iPoints = new ( ELeave ) TPoint16[iPointsCountMax];
       
   102     iSegset = new ( ELeave ) TSegSet[iSegsetCountMax];
       
   103     iEdges = new ( ELeave ) TGfxSegEdge[iEdgesCountMax];
       
   104     }
       
   105 
       
   106 
       
   107 // ---------------------------------------------------------------------------
       
   108 // reset
       
   109 // ---------------------------------------------------------------------------
       
   110 // --------------------------------------------------------------------------
       
   111 // void CGfxEdgeListP::Reset()
       
   112 // ---------------------------------------------------------------------------
       
   113 void CGfxEdgeListP::Reset()
       
   114     {
       
   115     // From CGfxEdgeListP
       
   116     iEdgesCount = 0;
       
   117     iLastSegLenSq = 0xffffffff;
       
   118     iPolygonAreaSize = 0;
       
   119     iMinX = KMAXFLOATFIX;
       
   120     iMinY = KMAXFLOATFIX;
       
   121     iMaxX = KMINFLOATFIX;
       
   122     iMaxY = KMINFLOATFIX;
       
   123 
       
   124     iPointsCount = 0;
       
   125     iSegsetCount = 0;
       
   126 
       
   127     iActiveSegList = 0;
       
   128     iWaitingSegList = 0;
       
   129     iSortedEdges = 0;
       
   130 
       
   131     iStartSeg = iSegset;
       
   132     iIsNewOutlineStarted = EFalse;
       
   133     iSubPathSegmentCount = 0;
       
   134     }
       
   135 
       
   136 // --------------------------------------------------------------------------
       
   137 // void CGfxEdgeListP::AdjustShapeComplexityL( TInt32 aVertexSize )
       
   138 // ---------------------------------------------------------------------------
       
   139 void CGfxEdgeListP::AdjustShapeComplexityL( TInt32 aVertexSize )
       
   140     {
       
   141     if ( aVertexSize < iPointsCountMax )
       
   142         return;
       
   143     //
       
   144     delete[] iPoints;
       
   145     delete[] iSegset;
       
   146     delete[] iEdges;
       
   147     iPoints = NULL;
       
   148     iSegset = NULL;
       
   149     iEdges = NULL;
       
   150     iPointsCountMax = aVertexSize + 4;
       
   151     iSegsetCountMax = aVertexSize;
       
   152     iEdgesCountMax = aVertexSize;
       
   153     iPoints = new ( ELeave ) TPoint16[iPointsCountMax];
       
   154     iSegset = new ( ELeave ) TSegSet[iSegsetCountMax];
       
   155     iEdges = new ( ELeave ) TGfxSegEdge[iEdgesCountMax];
       
   156     }
       
   157 
       
   158 // --------------------------------------------------------------------------
       
   159 // void CGfxEdgeListP::StartPoint( TFixPt& aX, TFixPt& aY )
       
   160 // ---------------------------------------------------------------------------
       
   161 void CGfxEdgeListP::StartPoint( TFixPt& aX, TFixPt& aY )
       
   162     {
       
   163     if ( iPointsCount >= iPointsCountMax - 1 ) // No more segments?
       
   164         return;
       
   165 
       
   166     // New segment set. Add one point and set flag
       
   167     TPoint16& p1 = iPoints[iPointsCount++];
       
   168     p1.iX = ( TInt16 ) ( TInt ) aX;
       
   169     p1.iY = ( TInt16 ) ( TInt ) aY;
       
   170 
       
   171     // Min/Max update
       
   172     if ( p1.iY < iMinY )
       
   173         iMinY = p1.iY;
       
   174     else if ( p1.iY > iMaxY )
       
   175         iMaxY = p1.iY;
       
   176     if ( p1.iX < iMinX )
       
   177         iMinX = p1.iX;
       
   178     else if ( p1.iX > iMaxX )
       
   179         iMaxX = p1.iX;
       
   180 
       
   181     iIsNewOutlineStarted = ETrue;
       
   182     iSubPathSegmentCount = 0;
       
   183     }
       
   184 
       
   185 // --------------------------------------------------------------------------
       
   186 // void CGfxEdgeListP::AddPoint( TFixPt& aX, TFixPt& aY, TBool aFillOnly, TBool aClosePath )
       
   187 // ---------------------------------------------------------------------------
       
   188 void CGfxEdgeListP::AddPoint( TFixPt& aX, TFixPt& aY, TBool aFillOnly, TBool aClosePath )
       
   189     {
       
   190     if ( iPointsCount >= iPointsCountMax - 1 ) // No more segments?
       
   191         return;
       
   192 
       
   193     TBool newSegsetFlag = EFalse;
       
   194     TBool completeSubPathFlag = EFalse;
       
   195 
       
   196     if ( iIsNewOutlineStarted )
       
   197         {
       
   198         CheckAndConnect();
       
   199         newSegsetFlag = ETrue;
       
   200         }
       
   201     else if ( aClosePath && ( iSubPathSegmentCount == 1 ) )
       
   202         {
       
   203         completeSubPathFlag = ETrue;
       
   204         newSegsetFlag = ETrue;
       
   205         }
       
   206     else
       
   207         {
       
   208         TInt x = ( TInt ) aX, y = ( TInt ) aY;
       
   209         switch ( iSegset[iSegsetCount - 1].AddSegment( x,
       
   210                                                        y,
       
   211                                                        iLastSegLenSq,
       
   212                                                        aClosePath ) )
       
   213             {
       
   214             case ESegAdd:
       
   215                 // Add point
       
   216                 iPointsCount++;
       
   217                 break;
       
   218             case ESegMerge:
       
   219                 // Do nothing
       
   220                 break;
       
   221             case ESegStartNew:
       
   222                 newSegsetFlag = ETrue;
       
   223                 break;
       
   224             default:
       
   225                 return;// ESegIgnore - do nothing
       
   226             }
       
   227         }
       
   228 
       
   229     if ( newSegsetFlag && iSegsetCount < iSegsetCountMax )
       
   230         {
       
   231         // New segment set. Add two points
       
   232         TPoint16* p =& iPoints[iPointsCount++];
       
   233         p->iX = ( TInt16 ) ( TInt ) aX;
       
   234         p->iY = ( TInt16 ) ( TInt ) aY;
       
   235 
       
   236         iSubPathSegmentCount++;
       
   237         TSegSet& seg = iSegset[iSegsetCount++];
       
   238         seg.Construct( p - 1, p );
       
   239 
       
   240         if ( iSegsetCount > 1 )
       
   241             iSegset[iSegsetCount - 2].iNext = &seg;
       
   242 
       
   243         if ( iIsNewOutlineStarted )
       
   244             iStartSeg = &seg;
       
   245 
       
   246         if ( completeSubPathFlag )      // (cdm)
       
   247             {
       
   248             iSegset[iSegsetCount - 1].iSign = -1;
       
   249             iSegset[iSegsetCount - 2].iSign = 1;
       
   250             iSegset[iSegsetCount - 1].iConnectFlag = EFalse;
       
   251             iSegset[iSegsetCount - 2].iConnectFlag = EFalse;
       
   252             }
       
   253         }
       
   254 
       
   255     // Min/Max update
       
   256     TPoint16& p = iPoints[iPointsCount - 1];
       
   257     if ( p.iY < iMinY )
       
   258         iMinY = p.iY;
       
   259     else if ( p.iY > iMaxY )
       
   260         iMaxY = p.iY;
       
   261     if ( p.iX < iMinX )
       
   262         iMinX = p.iX;
       
   263     else if ( p.iX > iMaxX )
       
   264         iMaxX = p.iX;
       
   265 
       
   266     if ( aFillOnly )
       
   267         {
       
   268         iSegset[iSegsetCount - 1].iFillOnlySeg = &iPoints[iPointsCount - 1];
       
   269         }
       
   270 
       
   271     iIsNewOutlineStarted = EFalse;
       
   272     }
       
   273 
       
   274 // --------------------------------------------------------------------------
       
   275 // void CGfxEdgeListP::SetupEdgeList()
       
   276 // ---------------------------------------------------------------------------
       
   277 void CGfxEdgeListP::SetupEdgeList()
       
   278     {
       
   279     TInt i;
       
   280 
       
   281     //
       
   282     CheckAndConnect();
       
   283 
       
   284     // Sort waiting list
       
   285     TSegSet* segset = iSegset;
       
   286     for ( i = 0; i < iSegsetCount; i++ )
       
   287         {
       
   288         if ( segset->iValid )
       
   289             {
       
   290             InsertToList( ETrue, * segset );
       
   291             if ( segset->iActualBottomY < 0 )
       
   292                 segset->iActualBottomY = segset->iBottomPoint->iY;
       
   293             }
       
   294         segset++;
       
   295         }
       
   296 
       
   297     // Normalize x coordinates
       
   298     for ( i = 0; i < iPointsCount; i++ )
       
   299         {
       
   300         iPoints[i].iX = ( TInt16 ) ( iPoints[i].iX - iMinX );
       
   301         }
       
   302 
       
   303     // Setting up for simple polygon, if applicable
       
   304     if ( iSegsetCount < 4 )
       
   305         {
       
   306         TInt ix = 0;
       
   307         segset = iWaitingSegList;
       
   308 
       
   309         iSegListForSimple[0] = iSegListForSimple[1] = NULL;     // (cdm).
       
   310 
       
   311         while ( segset )
       
   312             {
       
   313             if ( segset->iTopPoint->iY <= iMinY )
       
   314                 {
       
   315                 iSegListForSimple[ix++] = segset;
       
   316                 segset->InitDDA();
       
   317                 if ( ix > 2 )
       
   318                     break;
       
   319                 }
       
   320             segset = segset->iNext;
       
   321             }
       
   322         }
       
   323 
       
   324     }
       
   325 
       
   326 // --------------------------------------------------------------------------
       
   327 // void CGfxEdgeListP::UpdateActiveEdge( TInt aY )
       
   328 // ---------------------------------------------------------------------------
       
   329 void CGfxEdgeListP::UpdateActiveEdge( TInt aY )
       
   330     {
       
   331     // if number of segment is less than 4, it means the polygon is
       
   332     // a simple polygon, which we can reduce some processing.
       
   333     if ( iSegsetCount < 4 )
       
   334         {
       
   335         UpdateActiveEdgeSimple( aY );
       
   336         return;
       
   337         }
       
   338 
       
   339     // Remove from active segment list
       
   340     while ( iActiveSegList )
       
   341         {
       
   342         if ( aY <= iActiveSegList->iActualBottomY )
       
   343             break;
       
   344 
       
   345 
       
   346         iActiveSegList = iActiveSegList->iNext;
       
   347         }
       
   348 
       
   349     // Add newly activated segment to active segment list
       
   350     while ( iWaitingSegList )
       
   351         {
       
   352         if ( aY < iWaitingSegList->iTopPoint->iY )
       
   353             break;
       
   354         TSegSet* seg = iWaitingSegList;
       
   355         iWaitingSegList = iWaitingSegList->iNext;
       
   356 
       
   357         InsertToList( EFalse, * seg );  // add to active list
       
   358 
       
   359         seg->InitDDA();
       
   360         }
       
   361 
       
   362     // Add edges from active segements
       
   363     TSegSet* asl = iActiveSegList;
       
   364     TGfxSegEdge* edge;
       
   365     TInt x1, x2;
       
   366     TBool fillOnly;
       
   367 
       
   368     iSortedEdges = 0;
       
   369     iEdgesCount = 0;
       
   370     while ( asl )
       
   371         {
       
   372         fillOnly = asl->GetEdge( x1, x2 );
       
   373         edge = AddEdge( x1, x2 );
       
   374         if ( !edge )    // no more edges can be added.
       
   375             return;
       
   376         edge->iSign = ( TInt16 ) asl->iSign;
       
   377         edge->iOnlyForFill = ( TInt16 ) fillOnly;
       
   378 
       
   379         asl = asl->iNext;
       
   380         }
       
   381     }
       
   382 
       
   383 // --------------------------------------------------------------------------
       
   384 // TGfxSegEdge* CGfxEdgeListP::EdgeList()
       
   385 // ---------------------------------------------------------------------------
       
   386 TGfxSegEdge* CGfxEdgeListP::EdgeList()
       
   387     {
       
   388     return iSortedEdges;
       
   389     }
       
   390 
       
   391 // --------------------------------------------------------------------------
       
   392 // void CGfxEdgeListP::UpdateActiveEdgeSimple( TInt aY )   // (cdm)
       
   393 // ---------------------------------------------------------------------------
       
   394 void CGfxEdgeListP::UpdateActiveEdgeSimple( TInt aY )   // (cdm)
       
   395     {
       
   396     // Add edges from active segments
       
   397     TGfxSegEdge* edge;
       
   398     TInt x01, x02, x11, x12;
       
   399     TBool fillOnly0, fillOnly1;
       
   400     iEdgesCount = 0;
       
   401 
       
   402     if ( iSegListForSimple[0] && iSegListForSimple[1] )
       
   403         {
       
   404 
       
   405         if ( aY > iSegListForSimple[0]->iActualBottomY ) // (cdm)
       
   406             iSegListForSimple[0] = iSegListForSimple[0]->iNext;
       
   407 
       
   408         if ( aY > iSegListForSimple[1]->iActualBottomY )
       
   409             iSegListForSimple[1] = iSegListForSimple[1]->iNext;
       
   410 
       
   411         if ( !iSegListForSimple[0] || !iSegListForSimple[1] )
       
   412             return;
       
   413 
       
   414         iEdgesCount = 2;
       
   415         fillOnly0 = iSegListForSimple[0]->GetEdge( x01, x02 );
       
   416         fillOnly1 = iSegListForSimple[1]->GetEdge( x11, x12 );
       
   417 
       
   418         if ( x01 < x11 )
       
   419             {
       
   420             // iSegListForSimple[0] is left
       
   421             iSortedEdges = iEdges;
       
   422             edge = iSortedEdges;
       
   423             edge->iStart = ( TInt16 ) x01;
       
   424             edge->iEnd = ( TInt16 ) x02;
       
   425             edge->iSign = ( TInt16 ) iSegListForSimple[0]->iSign;
       
   426             edge->iOnlyForFill = ( TInt16 ) fillOnly0;
       
   427             edge->iNext = iEdges + 1;
       
   428 
       
   429             edge = edge->iNext;
       
   430             edge->iStart = ( TInt16 ) x11;
       
   431             edge->iEnd = ( TInt16 ) x12;
       
   432             edge->iSign = ( TInt16 ) iSegListForSimple[1]->iSign;
       
   433             edge->iOnlyForFill = ( TInt16 ) fillOnly1;
       
   434             edge->iNext = NULL;
       
   435             }
       
   436         else
       
   437             {
       
   438             // iSegListForSimple[1] is left
       
   439             iSortedEdges = iEdges;
       
   440             edge = iSortedEdges;
       
   441             edge->iStart = ( TInt16 ) x11;
       
   442             edge->iEnd = ( TInt16 ) x12;
       
   443             edge->iSign = ( TInt16 ) iSegListForSimple[1]->iSign;
       
   444             edge->iOnlyForFill = ( TInt16 ) fillOnly1;
       
   445             edge->iNext = iEdges + 1;
       
   446 
       
   447             edge = edge->iNext;
       
   448             edge->iStart = ( TInt16 ) x01;
       
   449             edge->iEnd = ( TInt16 ) x02;
       
   450             edge->iSign = ( TInt16 ) iSegListForSimple[0]->iSign;
       
   451             edge->iOnlyForFill = ( TInt16 ) fillOnly0;
       
   452             edge->iNext = NULL;
       
   453             }
       
   454         }
       
   455     }
       
   456 
       
   457 // --------------------------------------------------------------------------
       
   458 // void CGfxEdgeListP::InsertToList( TBool aWaitingList, TSegSet& aSegSet )
       
   459 // ---------------------------------------------------------------------------
       
   460 void CGfxEdgeListP::InsertToList( TBool aWaitingList, TSegSet& aSegSet )
       
   461     {
       
   462     TSegSet** next;
       
   463     if ( aWaitingList )
       
   464         next = &iWaitingSegList;
       
   465     else
       
   466         next = &iActiveSegList;
       
   467 	if(aWaitingList)
       
   468 	{
       
   469 		while ( *next )
       
   470 			{
       
   471 	            if ( ( *next )->iTopPoint->iY >= aSegSet.iTopPoint->iY )
       
   472                 break;
       
   473 		        next = &( ( *next )->iNext );
       
   474             }
       
   475 	}
       
   476     else
       
   477     {
       
   478 		while( *next )
       
   479 			{
       
   480             if ( ( *next )->iActualBottomY >= aSegSet.iActualBottomY )
       
   481                 break;
       
   482 	        next = &( ( *next )->iNext );
       
   483 
       
   484             }
       
   485     }
       
   486     //
       
   487     aSegSet.iNext = *next;
       
   488     *next = &aSegSet;
       
   489     }
       
   490 
       
   491 // --------------------------------------------------------------------------
       
   492 // TGfxSegEdge* CGfxEdgeListP::AddEdge( TInt32 aSt, TInt32 aEd )//, TInt aSegSign)
       
   493 // ---------------------------------------------------------------------------
       
   494 TGfxSegEdge* CGfxEdgeListP::AddEdge( TInt32 aSt, TInt32 aEd )//, TInt aSegSign)
       
   495 {
       
   496     if ( iEdgesCount >= iEdgesCountMax - 1 ) // No more edges?
       
   497         return NULL;
       
   498 
       
   499     TGfxSegEdge& newEdge = iEdges[iEdgesCount++];
       
   500     newEdge.iStart = ( TInt16 ) aSt;
       
   501     newEdge.iEnd = ( TInt16 ) aEd;
       
   502 
       
   503     // Insert this edge in sorted link list
       
   504     TGfxSegEdge** next;
       
   505     next = &iSortedEdges;
       
   506     TInt16 lastEnd = KMINFLOATFIX;
       
   507     while ( *next )
       
   508         {
       
   509         if ( newEdge.iStart < ( *next )->iStart )       // (cdm).
       
   510             break;
       
   511 
       
   512         lastEnd = ( *next )->iEnd;
       
   513         next = &( ( *next )->iNext );
       
   514         }
       
   515     //
       
   516     newEdge.iNext = *next;
       
   517     *next = &newEdge;
       
   518 
       
   519     return &newEdge;
       
   520     }
       
   521 
       
   522 // --------------------------------------------------------------------------
       
   523 // void CGfxEdgeListP::CheckAndConnect()
       
   524 // ---------------------------------------------------------------------------
       
   525 void CGfxEdgeListP::CheckAndConnect()
       
   526     {
       
   527     if ( iSegsetCount < 3 )     // (cdm)
       
   528         return;
       
   529 
       
   530     // Merge the first one and the last one if they have same sign
       
   531     TSegSet* lastSegset =& iSegset[iSegsetCount - 1];
       
   532     TPoint16* ps1 = iStartSeg->iTopPoint;
       
   533     TPoint16* ps2 = iStartSeg->iBottomPoint;
       
   534     TPoint16* pl1 = lastSegset->iTopPoint;
       
   535     TPoint16* pl2 = lastSegset->iBottomPoint;
       
   536 
       
   537     if ( iStartSeg->iPointAryInc == lastSegset->iPointAryInc &&
       
   538         iStartSeg->iConnectFlag &&
       
   539          ( ( ps1->iX == pl1->iX && ps1->iY == pl1->iY ) ||
       
   540            ( ps1->iX == pl2->iX && ps1->iY == pl2->iY ) ||
       
   541            ( ps2->iX == pl1->iX && ps2->iY == pl1->iY ) ||
       
   542            ( ps2->iX == pl2->iX && ps2->iY == pl2->iY ) ) )
       
   543         {
       
   544         if ( iStartSeg->iPointAryInc == 1 )
       
   545             {
       
   546             iStartSeg->iValid = EFalse;
       
   547             lastSegset->iConnect = iStartSeg;
       
   548             lastSegset->iActualBottomY = iStartSeg->iBottomPoint->iY;
       
   549             }
       
   550         else
       
   551             {
       
   552             lastSegset->iValid = EFalse;
       
   553             iStartSeg->iConnect = lastSegset;
       
   554             iStartSeg->iActualBottomY = lastSegset->iBottomPoint->iY;
       
   555             }
       
   556         }
       
   557     }
       
   558 
       
   559 void TSegSet::Construct( TPoint16* aP1, TPoint16* aP2 )
       
   560     {
       
   561     if ( aP1->iY < aP2->iY )
       
   562         {
       
   563         iTopPoint = aP1;
       
   564         iBottomPoint = aP2;
       
   565         iSign = 1;
       
   566         iPointAryInc = 1;
       
   567         }
       
   568     else if ( aP1->iY == aP2->iY )
       
   569         {
       
   570         iTopPoint = aP1;
       
   571         iBottomPoint = aP2;
       
   572         iSign = 0;
       
   573         iPointAryInc = 1;
       
   574         }
       
   575     else
       
   576         {
       
   577         iTopPoint = aP2;
       
   578         iBottomPoint = aP1;
       
   579         iSign = -1;
       
   580         iPointAryInc = -1;
       
   581         }
       
   582 
       
   583     iNext = NULL;
       
   584     iConnect = NULL;
       
   585     iValid = ETrue;
       
   586     iActualBottomY = KMINFLOATFIX;
       
   587     iFillOnlySeg = NULL;
       
   588     iConnectFlag = ETrue;
       
   589     }
       
   590 
       
   591 TAddSegStatus TSegSet::AddSegment( TInt aX,
       
   592                                    TInt aY,
       
   593                                    TUint& aLastSegLenSq,
       
   594                                    TBool aClosePath )
       
   595     {
       
   596     TPoint16* p;    // the last vertex in the array of vertex
       
   597     if ( iPointAryInc == 1 )
       
   598         p = iBottomPoint;
       
   599     else
       
   600         p = iTopPoint;
       
   601 
       
   602     // Check sign of y diff
       
   603     TInt16 x3 = ( TInt16 ) aX, y3 = ( TInt16 ) aY;
       
   604 
       
   605     if ( p->iX == x3 && p->iY == y3 )
       
   606         return ESegIgnore;
       
   607 
       
   608     TInt sign;
       
   609     if ( p->iY < y3 )
       
   610         sign = 1;
       
   611     else if ( p->iY == y3 )
       
   612         sign = 0;
       
   613     else
       
   614         sign = -1;
       
   615     if ( iSign == 0 )
       
   616         {
       
   617         iSign = ( TInt16 ) sign;
       
   618         if ( sign == -1 )
       
   619             {
       
   620             // swap top point and bottom point
       
   621             TPoint16* tmp = iTopPoint;
       
   622             iTopPoint = iBottomPoint;
       
   623             iBottomPoint = tmp;
       
   624             iPointAryInc = -1;
       
   625             }
       
   626         }
       
   627     else if ( sign != 0 && iSign != sign )
       
   628         return ESegStartNew;    // sign is different. start new segment
       
   629 
       
   630     // Vertex merging
       
   631     TUint lenSq = ( p->iX - x3 ) * ( p->iX - x3 ) +
       
   632                   ( p->iY - y3 ) * ( p->iY - y3 );
       
   633     if ( !aClosePath )
       
   634         {
       
   635         if ( aLastSegLenSq < 9 && lenSq < 9 )
       
   636             {
       
   637             p->iX = x3;
       
   638             p->iY = y3;
       
   639             TPoint16* pp = p + iPointAryInc;
       
   640             aLastSegLenSq = ( p->iX - pp->iX ) * ( p->iX - pp->iX ) +
       
   641                             ( p->iY - pp->iY ) * ( p->iY - pp->iY );
       
   642             return ESegMerge;
       
   643             }
       
   644         }
       
   645     aLastSegLenSq = lenSq;
       
   646 
       
   647 
       
   648     // Add point
       
   649     TPoint16* nextp;
       
   650     if ( iPointAryInc == 1 )
       
   651         nextp = ++iBottomPoint;
       
   652     else
       
   653         nextp = ++iTopPoint;
       
   654     nextp->iX = x3;
       
   655     nextp->iY = y3;
       
   656 
       
   657     return ESegAdd;
       
   658     }
       
   659 
       
   660 TBool TSegSet::GetEdge( TInt& aX1, TInt& aX2 )
       
   661     {
       
   662     TPoint16 p1, p2;
       
   663     TBool fillOnly;
       
   664     TBool done = SingleScanline( p1, p2 );
       
   665 
       
   666     if ( p1.iX < p2.iX )
       
   667         {
       
   668         aX1 = p1.iX;
       
   669         aX2 = p2.iX;
       
   670         }
       
   671     else
       
   672         {
       
   673         aX1 = p2.iX;
       
   674         aX2 = p1.iX;
       
   675         }
       
   676 
       
   677     if ( done )   // if done, construct new DDA with next segment
       
   678         {
       
   679         do
       
   680             {
       
   681             fillOnly = ( ( iTopPoint += iPointAryInc ) == iFillOnlySeg ); // (cdm)
       
   682 
       
   683             if ( iTopPoint == iBottomPoint )
       
   684                 {
       
   685                 if ( iConnect )
       
   686                     {
       
   687                     iTopPoint = iConnect->iTopPoint;
       
   688                     iBottomPoint = iConnect->iBottomPoint;
       
   689                     iFillOnlySeg = iConnect->iFillOnlySeg;
       
   690                     iConnect = NULL;
       
   691                     }
       
   692                 else
       
   693                     {
       
   694                     return fillOnly;
       
   695                     }
       
   696                 }
       
   697             ConstructDDA( iTopPoint, iTopPoint + iPointAryInc );
       
   698 
       
   699             done = SingleScanline( p1, p2 );
       
   700 
       
   701             if ( p1.iX < p2.iX )  // update edge minX & maxX
       
   702                 {
       
   703                 if ( p1.iX < aX1 )
       
   704                     aX1 = p1.iX;
       
   705                 if ( aX2 < p2.iX )
       
   706                     aX2 = p2.iX;
       
   707                 }
       
   708             else
       
   709                 {
       
   710                 if ( p2.iX < aX1 )
       
   711                     aX1 = p2.iX;
       
   712                 if ( aX2 < p1.iX )
       
   713                     aX2 = p1.iX;
       
   714                 }
       
   715             }
       
   716         while ( done );
       
   717         }
       
   718     else
       
   719         {
       
   720         fillOnly = ( iTopPoint == iFillOnlySeg || iTopPoint + iPointAryInc == iFillOnlySeg );
       
   721         }
       
   722     return fillOnly;
       
   723     }
       
   724 
       
   725 void TSegSet::InitDDA()
       
   726     {
       
   727     ConstructDDA( iTopPoint, iTopPoint + iPointAryInc );
       
   728     }
       
   729 
       
   730 // ---------------------------------------------------------------------------
       
   731 // DDA functions, which is mostly from Symbian's TLinearDDA
       
   732 // ---------------------------------------------------------------------------
       
   733 void TSegSet::ConstructDDA( TPoint16* aStart, TPoint16* aFinish )
       
   734     {
       
   735     iStart = aStart;
       
   736     iFinish = aFinish;
       
   737     iDifference.iWidth = ( TInt16 ) Abs( iStart->iX - iFinish->iX );
       
   738     iDifference.iHeight = ( TInt16 ) Abs( iStart->iY - iFinish->iY );
       
   739     iInc.iX = ( TInt16 ) ( ( iStart->iX > iFinish->iX ) ? -1 : 1 );
       
   740     iInc.iY = ( TInt16 ) ( ( iStart->iY > iFinish->iY ) ? -1 : 1 );
       
   741     if ( iDifference.iWidth )
       
   742         {
       
   743         iGradient = ( TInt16 )
       
   744                     ( ( iFinish->iY - iStart->iY ) /
       
   745                       ( iFinish->iX - iStart->iX ) );
       
   746         }
       
   747     else
       
   748         {
       
   749         iGradient = 0;  // (cdm)
       
   750         }
       
   751 
       
   752     iPos = *iStart;
       
   753     if ( !iGradient )
       
   754         {
       
   755         iCount = iDifference.iWidth;
       
   756         }
       
   757     else
       
   758         {
       
   759         iCount = iDifference.iHeight;
       
   760         }
       
   761     iCount >>= 1;
       
   762     iStatus = EInitialised;
       
   763     if ( aStart == aFinish )
       
   764         iStatus = EComplete;
       
   765     }
       
   766 
       
   767 TBool TSegSet::SingleStep( TPoint16& aPosition )
       
   768     {
       
   769     if ( iStatus == ECurrent )
       
   770         {
       
   771         UpdatePosition();
       
   772         aPosition = iPos;
       
   773         if ( iPos.iX == iFinish->iX && iPos.iY == iFinish->iY )
       
   774             {
       
   775             iStatus = EComplete;
       
   776             return( ETrue );
       
   777             }
       
   778         return( EFalse );
       
   779         }
       
   780     else if ( iStatus == EInitialised )
       
   781         {
       
   782         aPosition = *iStart;
       
   783         iStatus = ECurrent;
       
   784         return( EFalse );
       
   785         }
       
   786     else
       
   787         {
       
   788         aPosition = *iFinish;
       
   789         return( ETrue );
       
   790         };
       
   791     }
       
   792 
       
   793 TBool TSegSet::SingleScanline( TPoint16& aStartPosition,
       
   794                                TPoint16& aEndPosition )
       
   795     {
       
   796     TBool done = EFalse;
       
   797     if ( iDifference.iHeight == 0 )
       
   798         {
       
   799         aStartPosition = *iStart;
       
   800         aEndPosition = *iFinish;
       
   801         iStatus = EComplete;  //KM
       
   802         return( ETrue );
       
   803         }
       
   804     if ( iDifference.iWidth == 0 || iGradient )
       
   805         {
       
   806         done = SingleStep( aStartPosition );
       
   807         aEndPosition = aStartPosition;
       
   808         return( done );
       
   809         }
       
   810     done = SingleStep( aStartPosition );
       
   811     aEndPosition = aStartPosition;
       
   812     while ( iCount - iDifference.iHeight >= 0 && !done )
       
   813         {
       
   814         done = SingleStep( aEndPosition );
       
   815         }
       
   816     return( done );
       
   817     }
       
   818 
       
   819 void TSegSet::UpdatePosition()
       
   820     {
       
   821     if ( iDifference.iHeight == 0 ) // horizontal line
       
   822         iPos.iX = ( TInt16 ) ( iPos.iX + iInc.iX );
       
   823     else if ( iDifference.iWidth == 0 ) // vertical line
       
   824         iPos.iY = ( TInt16 ) ( iPos.iY + iInc.iY );
       
   825     else
       
   826         {
       
   827         if ( !iGradient )
       
   828             {
       
   829             iCount = ( TInt16 ) ( iCount - iDifference.iHeight );
       
   830             if ( iCount < 0 )
       
   831                 {
       
   832                 iCount = ( TInt16 ) ( iCount + iDifference.iWidth );
       
   833                 iPos.iY = ( TInt16 ) ( iPos.iY + iInc.iY );
       
   834                 }
       
   835             iPos.iX = ( TInt16 ) ( iPos.iX + iInc.iX );
       
   836             }
       
   837         else
       
   838             {
       
   839             iCount = ( TInt16 ) ( iCount - iDifference.iWidth );
       
   840             if ( iCount < 0 )
       
   841                 {
       
   842                 iCount = ( TInt16 ) ( iCount + iDifference.iHeight );
       
   843                 iPos.iX = ( TInt16 ) ( iPos.iX + iInc.iX );
       
   844                 }
       
   845             iPos.iY = ( TInt16 ) ( iPos.iY + iInc.iY );
       
   846             }
       
   847         }
       
   848     }