Author: tkreuzer Date: Tue Mar 10 00:11:43 2015 New Revision: 66645
URL: http://svn.reactos.org/svn/reactos?rev=66645&view=rev Log: [WIN32K] Apply proper formatting to polyfill.c
Modified: trunk/reactos/win32ss/gdi/ntgdi/polyfill.c
Modified: trunk/reactos/win32ss/gdi/ntgdi/polyfill.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/ntgdi/polyfill.... ============================================================================== --- trunk/reactos/win32ss/gdi/ntgdi/polyfill.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/gdi/ntgdi/polyfill.c [iso-8859-1] Tue Mar 10 00:11:43 2015 @@ -18,31 +18,31 @@ */ typedef struct _tagFILL_EDGE { - /* Basic line information */ - int FromX; - int FromY; - int ToX; - int ToY; - int dx; - int dy; - int absdx, absdy; - int x, y; - int xmajor; - - /* Active Edge List information */ - int XIntercept[2]; - int Error; - int ErrorMax; - int XDirection, YDirection; - - /* The next edge in the active Edge List */ - struct _tagFILL_EDGE * pNext; + /* Basic line information */ + int FromX; + int FromY; + int ToX; + int ToY; + int dx; + int dy; + int absdx, absdy; + int x, y; + int xmajor; + + /* Active Edge List information */ + int XIntercept[2]; + int Error; + int ErrorMax; + int XDirection, YDirection; + + /* The next edge in the active Edge List */ + struct _tagFILL_EDGE * pNext; } FILL_EDGE;
typedef struct _FILL_EDGE_LIST { - int Count; - FILL_EDGE** Edges; + int Count; + FILL_EDGE** Edges; } FILL_EDGE_LIST;
#if 0 @@ -50,19 +50,19 @@ void DEBUG_PRINT_ACTIVE_EDGELIST ( FILL_EDGE* list ) { - FILL_EDGE* pThis = list; - if (0 == list) - { - DPRINT1("List is NULL\n"); - return; - } - - while(0 != pThis) - { - //DPRINT1("EDGE: (%d, %d) to (%d, %d)\n", pThis->FromX, pThis->FromY, pThis->ToX, pThis->ToY); - DPRINT1("EDGE: [%d,%d]\n", pThis->XIntercept[0], pThis->XIntercept[1] ); - pThis = pThis->pNext; - } + FILL_EDGE* pThis = list; + if (0 == list) + { + DPRINT1("List is NULL\n"); + return; + } + + while(0 != pThis) + { + //DPRINT1("EDGE: (%d, %d) to (%d, %d)\n", pThis->FromX, pThis->FromY, pThis->ToX, pThis->ToY); + DPRINT1("EDGE: [%d,%d]\n", pThis->XIntercept[0], pThis->XIntercept[1] ); + pThis = pThis->pNext; + } } #else #define DEBUG_PRINT_ACTIVE_EDGELIST(x) @@ -76,20 +76,23 @@ FASTCALL POLYGONFILL_DestroyEdgeList(FILL_EDGE_LIST* list) { - int i; - if ( list ) - { - if ( list->Edges ) - { - for ( i = 0; i < list->Count; i++ ) - { - if ( list->Edges[i] ) - EngFreeMem ( list->Edges[i] ); - } - EngFreeMem ( list->Edges ); - } - EngFreeMem ( list ); - } + int i; + + if (list) + { + if (list->Edges) + { + for (i = 0; i < list->Count; i++) + { + if (list->Edges[i]) + EngFreeMem(list->Edges[i]); + } + + EngFreeMem(list->Edges); + } + + EngFreeMem(list); + } }
/* @@ -100,57 +103,57 @@ FASTCALL POLYGONFILL_MakeEdge(POINT From, POINT To) { - FILL_EDGE* rc = (FILL_EDGE*)EngAllocMem(FL_ZERO_MEMORY, sizeof(FILL_EDGE), FILL_EDGE_ALLOC_TAG); - - if (0 == rc) - return NULL; - - //DPRINT1("Making Edge: (%d, %d) to (%d, %d)\n", From.x, From.y, To.x, To.y); - // Now fill the struct. - if ( To.y < From.y ) - { - rc->FromX = To.x; - rc->FromY = To.y; - rc->ToX = From.x; - rc->ToY = From.y; - rc->YDirection = -1; - - // Lines that go up get walked backwards, so need to be offset - // by -1 in order to make the walk identically on a pixel-level - rc->Error = -1; - } - else - { - rc->FromX = From.x; - rc->FromY = From.y; - rc->ToX = To.x; - rc->ToY = To.y; - rc->YDirection = 1; - - rc->Error = 0; - } - - rc->x = rc->FromX; - rc->y = rc->FromY; - rc->dx = rc->ToX - rc->FromX; - rc->dy = rc->ToY - rc->FromY; - rc->absdx = abs(rc->dx); - rc->absdy = abs(rc->dy); - - rc->xmajor = rc->absdx > rc->absdy; - - rc->ErrorMax = max(rc->absdx,rc->absdy); - - rc->Error += rc->ErrorMax / 2; - - rc->XDirection = (rc->dx < 0)?(-1):(1); - - rc->pNext = 0; - - //DPRINT("MakeEdge (%i,%i)->(%i,%i) d=(%i,%i) dir=(%i,%i) err=%i max=%i\n", - // From.x, From.y, To.x, To.y, rc->dx, rc->dy, rc->XDirection, rc->YDirection, rc->Error, rc->ErrorMax ); - - return rc; + FILL_EDGE* rc = (FILL_EDGE*)EngAllocMem(FL_ZERO_MEMORY, sizeof(FILL_EDGE), FILL_EDGE_ALLOC_TAG); + + if (0 == rc) + return NULL; + + //DPRINT1("Making Edge: (%d, %d) to (%d, %d)\n", From.x, From.y, To.x, To.y); + // Now fill the struct. + if ( To.y < From.y ) + { + rc->FromX = To.x; + rc->FromY = To.y; + rc->ToX = From.x; + rc->ToY = From.y; + rc->YDirection = -1; + + // Lines that go up get walked backwards, so need to be offset + // by -1 in order to make the walk identically on a pixel-level + rc->Error = -1; + } + else + { + rc->FromX = From.x; + rc->FromY = From.y; + rc->ToX = To.x; + rc->ToY = To.y; + rc->YDirection = 1; + + rc->Error = 0; + } + + rc->x = rc->FromX; + rc->y = rc->FromY; + rc->dx = rc->ToX - rc->FromX; + rc->dy = rc->ToY - rc->FromY; + rc->absdx = abs(rc->dx); + rc->absdy = abs(rc->dy); + + rc->xmajor = rc->absdx > rc->absdy; + + rc->ErrorMax = max(rc->absdx,rc->absdy); + + rc->Error += rc->ErrorMax / 2; + + rc->XDirection = (rc->dx < 0)?(-1):(1); + + rc->pNext = 0; + + //DPRINT("MakeEdge (%i,%i)->(%i,%i) d=(%i,%i) dir=(%i,%i) err=%i max=%i\n", + // From.x, From.y, To.x, To.y, rc->dx, rc->dy, rc->XDirection, rc->YDirection, rc->Error, rc->ErrorMax ); + + return rc; } /* ** My Edge comparison routine. @@ -171,10 +174,10 @@ FASTCALL FILL_EDGE_Compare(FILL_EDGE* Edge1, FILL_EDGE* Edge2) { - int e1 = Edge1->XIntercept[0] + Edge1->XIntercept[1]; - int e2 = Edge2->XIntercept[0] + Edge2->XIntercept[1]; - - return e1 - e2; + int e1 = Edge1->XIntercept[0] + Edge1->XIntercept[1]; + int e2 = Edge2->XIntercept[0] + Edge2->XIntercept[1]; + + return e1 - e2; }
@@ -186,39 +189,41 @@ FASTCALL POLYGONFILL_ActiveListInsert(FILL_EDGE** activehead, FILL_EDGE* NewEdge ) { - FILL_EDGE *pPrev, *pThis; - //DPRINT1("In POLYGONFILL_ActiveListInsert()\n"); - ASSERT ( activehead && NewEdge ); - if ( !*activehead ) - { - NewEdge->pNext = NULL; - *activehead = NewEdge; - return; - } - /* - ** First lets check to see if we have a new smallest value. - */ - if (FILL_EDGE_Compare(NewEdge, *activehead) <= 0) - { - NewEdge->pNext = *activehead; - *activehead = NewEdge; - return; - } - /* - ** Ok, now scan to the next spot to put this item. - */ - pThis = *activehead; - pPrev = NULL; - while ( pThis && FILL_EDGE_Compare(pThis, NewEdge) < 0 ) - { - pPrev = pThis; - pThis = pThis->pNext; - } - - ASSERT(pPrev); - NewEdge->pNext = pPrev->pNext; - pPrev->pNext = NewEdge; - //DEBUG_PRINT_ACTIVE_EDGELIST(*activehead); + FILL_EDGE *pPrev, *pThis; + //DPRINT1("In POLYGONFILL_ActiveListInsert()\n"); + ASSERT(activehead && NewEdge); + + if (!*activehead) + { + NewEdge->pNext = NULL; + *activehead = NewEdge; + return; + } + /* + ** First lets check to see if we have a new smallest value. + */ + if (FILL_EDGE_Compare(NewEdge, *activehead) <= 0) + { + NewEdge->pNext = *activehead; + *activehead = NewEdge; + return; + } + + /* + ** Ok, now scan to the next spot to put this item. + */ + pThis = *activehead; + pPrev = NULL; + while ( pThis && FILL_EDGE_Compare(pThis, NewEdge) < 0 ) + { + pPrev = pThis; + pThis = pThis->pNext; + } + + ASSERT(pPrev); + NewEdge->pNext = pPrev->pNext; + pPrev->pNext = NewEdge; + //DEBUG_PRINT_ACTIVE_EDGELIST(*activehead); }
/* @@ -229,50 +234,50 @@ FASTCALL POLYGONFILL_MakeEdgeList(PPOINT Points, int Count) { - int CurPt = 0; - FILL_EDGE_LIST* list = 0; - FILL_EDGE* e = 0; - - if ( 0 == Points || 2 > Count ) + int CurPt = 0; + FILL_EDGE_LIST* list = 0; + FILL_EDGE* e = 0; + + if (0 == Points || 2 > Count) + return 0; + + list = (FILL_EDGE_LIST*)EngAllocMem(FL_ZERO_MEMORY, sizeof(FILL_EDGE_LIST), FILL_EDGE_ALLOC_TAG); + if ( 0 == list ) + goto fail; + list->Count = 0; + list->Edges = (FILL_EDGE**)EngAllocMem(FL_ZERO_MEMORY, Count*sizeof(FILL_EDGE*), FILL_EDGE_ALLOC_TAG); + if ( !list->Edges ) + goto fail; + + memset(list->Edges, 0, Count * sizeof(FILL_EDGE*)); + + for (CurPt = 1; CurPt < Count; ++CurPt) + { + e = POLYGONFILL_MakeEdge ( Points[CurPt-1], Points[CurPt] ); + if (!e) + goto fail; + + // If a straight horizontal line - who cares? + if (!e->absdy) + EngFreeMem(e); + else + list->Edges[list->Count++] = e; + } + e = POLYGONFILL_MakeEdge ( Points[CurPt-1], Points[0] ); + if ( !e ) + goto fail; + + if (!e->absdy) + EngFreeMem(e); + else + list->Edges[list->Count++] = e; + return list; + +fail: + + DPRINT1("Out Of MEMORY!!\n"); + POLYGONFILL_DestroyEdgeList ( list ); return 0; - - list = (FILL_EDGE_LIST*)EngAllocMem(FL_ZERO_MEMORY, sizeof(FILL_EDGE_LIST), FILL_EDGE_ALLOC_TAG); - if ( 0 == list ) - goto fail; - list->Count = 0; - list->Edges = (FILL_EDGE**)EngAllocMem(FL_ZERO_MEMORY, Count*sizeof(FILL_EDGE*), FILL_EDGE_ALLOC_TAG); - if ( !list->Edges ) - goto fail; - - memset ( list->Edges, 0, Count * sizeof(FILL_EDGE*) ); - - for ( CurPt = 1; CurPt < Count; ++CurPt ) - { - e = POLYGONFILL_MakeEdge ( Points[CurPt-1], Points[CurPt] ); - if ( !e ) - goto fail; - - // If a straight horizontal line - who cares? - if ( !e->absdy ) - EngFreeMem ( e ); - else - list->Edges[list->Count++] = e; - } - e = POLYGONFILL_MakeEdge ( Points[CurPt-1], Points[0] ); - if ( !e ) - goto fail; - - if ( !e->absdy ) - EngFreeMem ( e ); - else - list->Edges[list->Count++] = e; - return list; - -fail: - - DPRINT1("Out Of MEMORY!!\n"); - POLYGONFILL_DestroyEdgeList ( list ); - return 0; }
@@ -287,63 +292,63 @@ FASTCALL POLYGONFILL_UpdateScanline(FILL_EDGE* pEdge, int Scanline) { - if ( 0 == pEdge->dy ) - return; - - ASSERT ( pEdge->FromY <= Scanline && pEdge->ToY > Scanline ); - - if ( pEdge->xmajor ) - { - int steps; - - ASSERT ( pEdge->y == Scanline ); - - // Now shoot to end of scanline collision - steps = (pEdge->ErrorMax-pEdge->Error-1)/pEdge->absdy; - if ( steps ) - { - // Record first collision with scanline - int x1 = pEdge->x; - pEdge->x += steps * pEdge->XDirection; - pEdge->Error += steps * pEdge->absdy; - ASSERT ( pEdge->Error < pEdge->ErrorMax ); - pEdge->XIntercept[0] = min(x1,pEdge->x); - pEdge->XIntercept[1] = max(x1,pEdge->x); - } - else - { - pEdge->XIntercept[0] = pEdge->x; - pEdge->XIntercept[1] = pEdge->x; - } - - // We should require exactly 1 step to step onto next scanline... - ASSERT ( (pEdge->ErrorMax-pEdge->Error-1) / pEdge->absdy == 0 ); - pEdge->x += pEdge->XDirection; - pEdge->Error += pEdge->absdy; - ASSERT ( pEdge->Error >= pEdge->ErrorMax ); - - // Now step onto next scanline... - pEdge->Error -= pEdge->absdx; - pEdge->y++; - } - else // Then this is a y-major line - { - pEdge->XIntercept[0] = pEdge->x; - pEdge->XIntercept[1] = pEdge->x; - - pEdge->Error += pEdge->absdx; - pEdge->y++; - - if ( pEdge->Error >= pEdge->ErrorMax ) - { - pEdge->Error -= pEdge->ErrorMax; - pEdge->x += pEdge->XDirection; - ASSERT ( pEdge->Error < pEdge->ErrorMax ); - } - } - - //DPRINT("Line (%d, %d) to (%d, %d) intersects scanline %d at (%d,%d)\n", - // pEdge->FromX, pEdge->FromY, pEdge->ToX, pEdge->ToY, Scanline, pEdge->XIntercept[0], pEdge->XIntercept[1] ); + if (0 == pEdge->dy) + return; + + ASSERT(pEdge->FromY <= Scanline && pEdge->ToY > Scanline); + + if (pEdge->xmajor) + { + int steps; + + ASSERT(pEdge->y == Scanline); + + // Now shoot to end of scanline collision + steps = (pEdge->ErrorMax-pEdge->Error-1)/pEdge->absdy; + if (steps) + { + // Record first collision with scanline + int x1 = pEdge->x; + pEdge->x += steps * pEdge->XDirection; + pEdge->Error += steps * pEdge->absdy; + ASSERT ( pEdge->Error < pEdge->ErrorMax ); + pEdge->XIntercept[0] = min(x1,pEdge->x); + pEdge->XIntercept[1] = max(x1,pEdge->x); + } + else + { + pEdge->XIntercept[0] = pEdge->x; + pEdge->XIntercept[1] = pEdge->x; + } + + // We should require exactly 1 step to step onto next scanline... + ASSERT((pEdge->ErrorMax-pEdge->Error-1) / pEdge->absdy == 0); + pEdge->x += pEdge->XDirection; + pEdge->Error += pEdge->absdy; + ASSERT(pEdge->Error >= pEdge->ErrorMax); + + // Now step onto next scanline... + pEdge->Error -= pEdge->absdx; + pEdge->y++; + } + else // Then this is a y-major line + { + pEdge->XIntercept[0] = pEdge->x; + pEdge->XIntercept[1] = pEdge->x; + + pEdge->Error += pEdge->absdx; + pEdge->y++; + + if (pEdge->Error >= pEdge->ErrorMax) + { + pEdge->Error -= pEdge->ErrorMax; + pEdge->x += pEdge->XDirection; + ASSERT ( pEdge->Error < pEdge->ErrorMax ); + } + } + + //DPRINT("Line (%d, %d) to (%d, %d) intersects scanline %d at (%d,%d)\n", + // pEdge->FromX, pEdge->FromY, pEdge->ToX, pEdge->ToY, Scanline, pEdge->XIntercept[0], pEdge->XIntercept[1] ); }
/* @@ -352,22 +357,25 @@ static void APIENTRY -POLYGONFILL_BuildActiveList ( int Scanline, FILL_EDGE_LIST* list, FILL_EDGE** ActiveHead ) -{ - int i; - - ASSERT ( list && ActiveHead ); - *ActiveHead = 0; - for ( i = 0; i < list->Count; i++ ) - { - FILL_EDGE* pEdge = list->Edges[i]; - ASSERT(pEdge); - if ( pEdge->FromY <= Scanline && pEdge->ToY > Scanline ) - { - POLYGONFILL_UpdateScanline ( pEdge, Scanline ); - POLYGONFILL_ActiveListInsert ( ActiveHead, pEdge ); - } - } +POLYGONFILL_BuildActiveList( + int Scanline, + FILL_EDGE_LIST* list, + FILL_EDGE** ActiveHead) +{ + int i; + + ASSERT(list && ActiveHead); + *ActiveHead = 0; + for (i = 0; i < list->Count; i++) + { + FILL_EDGE* pEdge = list->Edges[i]; + ASSERT(pEdge); + if (pEdge->FromY <= Scanline && pEdge->ToY > Scanline) + { + POLYGONFILL_UpdateScanline(pEdge, Scanline); + POLYGONFILL_ActiveListInsert(ActiveHead, pEdge); + } + } }
/* @@ -378,202 +386,203 @@ void APIENTRY POLYGONFILL_FillScanLineAlternate( - PDC dc, - int ScanLine, - FILL_EDGE* ActiveHead, - SURFACE *psurf, - BRUSHOBJ *BrushObj, - MIX RopMode ) -{ - FILL_EDGE *pLeft, *pRight; - - if ( !ActiveHead ) - return; - - pLeft = ActiveHead; - pRight = pLeft->pNext; - ASSERT(pRight); - - while ( NULL != pRight ) - { - int x1 = pLeft->XIntercept[0]; - int x2 = pRight->XIntercept[1]; - if ( x2 > x1 ) - { - RECTL BoundRect; - BoundRect.top = ScanLine; - BoundRect.bottom = ScanLine + 1; - BoundRect.left = x1; - BoundRect.right = x2; - - //DPRINT("Fill Line (%d, %d) to (%d, %d)\n",x1, ScanLine, x2, ScanLine); - IntEngLineTo(&psurf->SurfObj, - &dc->co.ClipObj, - BrushObj, - x1, - ScanLine, - x2, - ScanLine, - &BoundRect, // Bounding rectangle - RopMode); // MIX - } - pLeft = pRight->pNext; - pRight = pLeft ? pLeft->pNext : NULL; - } -} - -static -void -APIENTRY -POLYGONFILL_FillScanLineWinding( - PDC dc, - int ScanLine, - FILL_EDGE* ActiveHead, - SURFACE *psurf, - BRUSHOBJ *BrushObj, - MIX RopMode ) -{ - FILL_EDGE *pLeft, *pRight; - int x1, x2, winding = 0; - RECTL BoundRect; - - if ( !ActiveHead ) - return; - - BoundRect.top = ScanLine; - BoundRect.bottom = ScanLine + 1; - - pLeft = ActiveHead; - winding = pLeft->YDirection; - pRight = pLeft->pNext; - ASSERT(pRight); - - // Setup first line... - x1 = pLeft->XIntercept[0]; - x2 = pRight->XIntercept[1]; - - pLeft = pRight; - pRight = pLeft->pNext; - winding += pLeft->YDirection; - - while ( NULL != pRight ) - { - int newx1 = pLeft->XIntercept[0]; - int newx2 = pRight->XIntercept[1]; - if ( winding ) - { - // Check and see if this new line touches the previous... - if ( (newx1 >= x1 && newx1 <= x2) - || (newx2 >= x1 && newx2 <= x2) - || (x1 >= newx1 && x1 <= newx2) - || (x2 >= newx2 && x2 <= newx2) - ) - { - // Yup, just tack it on to our existing line - x1 = min(x1,newx1); - x2 = max(x2,newx2); - } - else - { - // Nope - render the old line.. - BoundRect.left = x1; - BoundRect.right = x2; - - //DPRINT("Fill Line (%d, %d) to (%d, %d)\n",x1, ScanLine, x2, ScanLine); - IntEngLineTo(&psurf->SurfObj, - &dc->co.ClipObj, - BrushObj, - x1, - ScanLine, - x2, - ScanLine, - &BoundRect, // Bounding rectangle - RopMode); // MIX - - x1 = newx1; - x2 = newx2; - } - } - pLeft = pRight; - pRight = pLeft->pNext; - winding += pLeft->YDirection; - } - // There will always be a line left-over, render it now... - BoundRect.left = x1; - BoundRect.right = x2; - - //DPRINT("Fill Line (%d, %d) to (%d, %d)\n",x1, ScanLine, x2, ScanLine); - IntEngLineTo(&psurf->SurfObj, - &dc->co.ClipObj, - BrushObj, - x1, - ScanLine, - x2, - ScanLine, - &BoundRect, // Bounding rectangle - RopMode); // MIX -} - -// When the fill mode is ALTERNATE, GDI fills the area between odd-numbered and -// even-numbered polygon sides on each scan line. That is, GDI fills the area between the -// first and second side, between the third and fourth side, and so on. - -// WINDING Selects winding mode (fills any region with a nonzero winding value). -// When the fill mode is WINDING, GDI fills any region that has a nonzero winding value. -// This value is defined as the number of times a pen used to draw the polygon would go around the region. -// The direction of each edge of the polygon is important. - -BOOL -APIENTRY -FillPolygon( - PDC dc, - SURFACE *psurf, - BRUSHOBJ *BrushObj, - MIX RopMode, - CONST PPOINT Points, - int Count, - RECTL BoundRect ) -{ - FILL_EDGE_LIST *list = 0; - FILL_EDGE *ActiveHead = 0; - int ScanLine; - PDC_ATTR pdcattr = dc->pdcattr; - void - (APIENTRY *FillScanLine)( PDC dc, int ScanLine, FILL_EDGE* ActiveHead, SURFACE *psurf, BRUSHOBJ *BrushObj, - MIX RopMode ); - - //DPRINT("FillPolygon\n"); - - /* Create Edge List. */ - list = POLYGONFILL_MakeEdgeList(Points, Count); - /* DEBUG_PRINT_EDGELIST(list); */ - if (NULL == list) - return FALSE; - - if ( WINDING == pdcattr->jFillMode ) - FillScanLine = POLYGONFILL_FillScanLineWinding; - else /* Default */ - FillScanLine = POLYGONFILL_FillScanLineAlternate; - - /* For each Scanline from BoundRect.bottom to BoundRect.top, - * determine line segments to draw - */ - for ( ScanLine = BoundRect.top; ScanLine < BoundRect.bottom; ++ScanLine ) - { - POLYGONFILL_BuildActiveList(ScanLine, list, &ActiveHead); - //DEBUG_PRINT_ACTIVE_EDGELIST(ActiveHead); - FillScanLine ( dc, ScanLine, ActiveHead, psurf, BrushObj, RopMode ); - } - - /* Free Edge List. If any are left. */ - POLYGONFILL_DestroyEdgeList(list); - - return TRUE; + MIX RopMode ) +{ + FILL_EDGE *pLeft, *pRight; + + if (!ActiveHead) + return; + + pLeft = ActiveHead; + pRight = pLeft->pNext; + ASSERT(pRight); + + while (NULL != pRight) + { + int x1 = pLeft->XIntercept[0]; + int x2 = pRight->XIntercept[1]; + if (x2 > x1) + { + RECTL BoundRect; + BoundRect.top = ScanLine; + BoundRect.bottom = ScanLine + 1; + BoundRect.left = x1; + BoundRect.right = x2; + + //DPRINT("Fill Line (%d, %d) to (%d, %d)\n",x1, ScanLine, x2, ScanLine); + IntEngLineTo(&psurf->SurfObj, + &dc->co.ClipObj, + BrushObj, + x1, + ScanLine, + x2, + ScanLine, + &BoundRect, // Bounding rectangle + RopMode); // MIX + } + pLeft = pRight->pNext; + pRight = pLeft ? pLeft->pNext : NULL; + } +} + +static +void +APIENTRY +POLYGONFILL_FillScanLineWinding( + PDC dc, + int ScanLine, + FILL_EDGE* ActiveHead, + SURFACE *psurf, + BRUSHOBJ *BrushObj, + MIX RopMode ) +{ + FILL_EDGE *pLeft, *pRight; + int x1, x2, winding = 0; + RECTL BoundRect; + + if (!ActiveHead) + return; + + BoundRect.top = ScanLine; + BoundRect.bottom = ScanLine + 1; + + pLeft = ActiveHead; + winding = pLeft->YDirection; + pRight = pLeft->pNext; + ASSERT(pRight); + + // Setup first line... + x1 = pLeft->XIntercept[0]; + x2 = pRight->XIntercept[1]; + + pLeft = pRight; + pRight = pLeft->pNext; + winding += pLeft->YDirection; + + while ( NULL != pRight ) + { + int newx1 = pLeft->XIntercept[0]; + int newx2 = pRight->XIntercept[1]; + if ( winding ) + { + // Check and see if this new line touches the previous... + if ((newx1 >= x1 && newx1 <= x2) || + (newx2 >= x1 && newx2 <= x2) || + (x1 >= newx1 && x1 <= newx2) || + (x2 >= newx2 && x2 <= newx2)) + { + // Yup, just tack it on to our existing line + x1 = min(x1,newx1); + x2 = max(x2,newx2); + } + else + { + // Nope - render the old line.. + BoundRect.left = x1; + BoundRect.right = x2; + + //DPRINT("Fill Line (%d, %d) to (%d, %d)\n",x1, ScanLine, x2, ScanLine); + IntEngLineTo(&psurf->SurfObj, + &dc->co.ClipObj, + BrushObj, + x1, + ScanLine, + x2, + ScanLine, + &BoundRect, // Bounding rectangle + RopMode); // MIX + + x1 = newx1; + x2 = newx2; + } + } + + pLeft = pRight; + pRight = pLeft->pNext; + winding += pLeft->YDirection; + } + + // There will always be a line left-over, render it now... + BoundRect.left = x1; + BoundRect.right = x2; + + //DPRINT("Fill Line (%d, %d) to (%d, %d)\n",x1, ScanLine, x2, ScanLine); + IntEngLineTo(&psurf->SurfObj, + &dc->co.ClipObj, + BrushObj, + x1, + ScanLine, + x2, + ScanLine, + &BoundRect, // Bounding rectangle + RopMode); // MIX +} + +// When the fill mode is ALTERNATE, GDI fills the area between odd-numbered and +// even-numbered polygon sides on each scan line. That is, GDI fills the area between the +// first and second side, between the third and fourth side, and so on. + +// WINDING Selects winding mode (fills any region with a nonzero winding value). +// When the fill mode is WINDING, GDI fills any region that has a nonzero winding value. +// This value is defined as the number of times a pen used to draw the polygon would go around the region. +// The direction of each edge of the polygon is important. + +BOOL +APIENTRY +FillPolygon( + PDC dc, + SURFACE *psurf, + BRUSHOBJ *BrushObj, + MIX RopMode, + CONST PPOINT Points, + int Count, + RECTL BoundRect ) +{ + FILL_EDGE_LIST *list = 0; + FILL_EDGE *ActiveHead = 0; + int ScanLine; + PDC_ATTR pdcattr = dc->pdcattr; + void + (APIENTRY *FillScanLine)( + PDC dc, + int ScanLine, + FILL_EDGE* ActiveHead, + SURFACE *psurf, + BRUSHOBJ *BrushObj, + MIX RopMode); + + //DPRINT("FillPolygon\n"); + + /* Create Edge List. */ + list = POLYGONFILL_MakeEdgeList(Points, Count); + /* DEBUG_PRINT_EDGELIST(list); */ + if (NULL == list) + return FALSE; + + if (WINDING == pdcattr->jFillMode) + FillScanLine = POLYGONFILL_FillScanLineWinding; + else /* Default */ + FillScanLine = POLYGONFILL_FillScanLineAlternate; + + /* For each Scanline from BoundRect.bottom to BoundRect.top, + * determine line segments to draw + */ + for (ScanLine = BoundRect.top; ScanLine < BoundRect.bottom; ++ScanLine) + { + POLYGONFILL_BuildActiveList(ScanLine, list, &ActiveHead); + //DEBUG_PRINT_ACTIVE_EDGELIST(ActiveHead); + FillScanLine(dc, ScanLine, ActiveHead, psurf, BrushObj, RopMode); + } + + /* Free Edge List. If any are left. */ + POLYGONFILL_DestroyEdgeList(list); + + return TRUE; }
BOOL FASTCALL @@ -600,23 +609,24 @@ return FALSE;
/* For each Scanline from DestRect.top to DestRect.bottom, determine line segments to draw */ - for ( ScanLine = DestRect.top; ScanLine < DestRect.bottom; ++ScanLine ) + for (ScanLine = DestRect.top; ScanLine < DestRect.bottom; ++ScanLine) { POLYGONFILL_BuildActiveList(ScanLine, list, &ActiveHead); //DEBUG_PRINT_ACTIVE_EDGELIST(ActiveHead);
- if ( !ActiveHead ) - return FALSE; + if (!ActiveHead) + return FALSE;
pLeft = ActiveHead; pRight = pLeft->pNext; ASSERT(pRight);
- while ( NULL != pRight ) + while (NULL != pRight) { int x1 = pLeft->XIntercept[0]; int x2 = pRight->XIntercept[1]; - if ( x2 > x1 ) + + if (x2 > x1) { RECTL LineRect; LineRect.top = ScanLine; @@ -625,17 +635,18 @@ LineRect.right = x2;
IntEngBitBlt(&psurf->SurfObj, - NULL, - NULL, - &dc->co.ClipObj, - NULL, - &LineRect, - NULL, - NULL, - BrushObj, - BrushOrigin, - ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY)); + NULL, + NULL, + &dc->co.ClipObj, + NULL, + &LineRect, + NULL, + NULL, + BrushObj, + BrushOrigin, + ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY)); } + pLeft = pRight->pNext; pRight = pLeft ? pLeft->pNext : NULL; }