improvements to Polygon algo - commiting to get help on one last detail. Winding polygons now work and floating point code is eliminated.

svn path=/trunk/; revision=5591
This commit is contained in:
Royce Mitchell III 2003-08-15 18:51:32 +00:00
parent 4f6a2a6124
commit d4deb682ee
5 changed files with 606 additions and 518 deletions

View file

@ -1,4 +1,4 @@
# $Id: makefile,v 1.1 2003/03/19 16:03:02 mtempel Exp $ # $Id: makefile,v 1.2 2003/08/15 18:51:31 royce Exp $
PATH_TO_TOP = ../../.. PATH_TO_TOP = ../../..
@ -6,10 +6,12 @@ TARGET_NORC = yes
TARGET_TYPE = program TARGET_TYPE = program
TARGET_APPTYPE = console TARGET_APPTYPE = windows
TARGET_NAME = shaptest TARGET_NAME = shaptest
TARGET_CFLAGS = -Wall -Werror
TARGET_SDKLIBS = kernel32.a gdi32.a TARGET_SDKLIBS = kernel32.a gdi32.a
TARGET_OBJECTS = $(TARGET_NAME).o TARGET_OBJECTS = $(TARGET_NAME).o

View file

@ -15,90 +15,95 @@
HFONT tf; HFONT tf;
LRESULT WINAPI MainWndProc(HWND, UINT, WPARAM, LPARAM); LRESULT WINAPI MainWndProc(HWND, UINT, WPARAM, LPARAM);
void __stdcall PolygonTest(HDC Desktop) void PolygonTest ( HDC hdc )
{ {
HPEN BluePen; HPEN BluePen, OldPen;
HPEN OldPen; HBRUSH RedBrush, OldBrush;
HBRUSH RedBrush; DWORD Mode;
HBRUSH OldBrush; POINT PointsAlternate[] =
POINT lpPointsAlternate[5]; {
POINT lpPointsWinding[5]; { 20, 80 },
DWORD Mode; { 60, 20 },
{ 90, 80 },
{ 20, 40 },
{ 100, 40 }
};
POINT PointsWinding[] =
{
{ 130, 80 },
{ 170, 20 },
{ 200, 80 },
{ 130, 40 },
{ 210, 40 }
};
POINT Tri1[] =
{
{ 3, 3 },
{ 5, 3 },
{ 3, 5 }
};
POINT Tri2[] =
{
{ 7, 3 },
{ 7, 7 },
{ 3, 7 },
};
//create a pen to draw the shape //create a pen to draw the shape
BluePen = CreatePen(PS_SOLID, 3, RGB(0, 0, 0xff)); BluePen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0xff));
RedBrush = CreateSolidBrush(RGB(0xff, 0, 0)); RedBrush = CreateSolidBrush(RGB(0xff, 0, 0));
//initialize a set of points for alternate. //initialize a set of points for alternate.
lpPointsAlternate[0].x = 20; /*lpPointsAlternate[0].x = 20;
lpPointsAlternate[0].y = 80; //{20,80}; lpPointsAlternate[0].y = 80; //{20,80};
lpPointsAlternate[1].x = 60; lpPointsAlternate[1].x = 60;
lpPointsAlternate[1].y = 20; //{60,20}; lpPointsAlternate[1].y = 20; //{60,20};
lpPointsAlternate[2].x = 90; lpPointsAlternate[2].x = 90;
lpPointsAlternate[2].y = 80; //{90,80}; lpPointsAlternate[2].y = 80; //{90,80};
lpPointsAlternate[3].x = 20; lpPointsAlternate[3].x = 20;
lpPointsAlternate[3].y = 40; //{20,40}; lpPointsAlternate[3].y = 40; //{20,40};
lpPointsAlternate[4].x = 100; lpPointsAlternate[4].x = 100;
lpPointsAlternate[4].y = 40; //{100,40}; lpPointsAlternate[4].y = 40; //{100,40};
//initialize a set of points for winding. //initialize a set of points for winding.
lpPointsWinding[0].x = 130; lpPointsWinding[0].x = 130;
lpPointsWinding[0].y = 80; //{130,80}; lpPointsWinding[0].y = 80; //{130,80};
lpPointsWinding[1].x = 170; lpPointsWinding[1].x = 170;
lpPointsWinding[1].y = 20; //{170,20}; lpPointsWinding[1].y = 20; //{170,20};
lpPointsWinding[2].x = 200; lpPointsWinding[2].x = 200;
lpPointsWinding[2].y = 80; //{200,80}; lpPointsWinding[2].y = 80; //{200,80};
lpPointsWinding[3].x = 130; lpPointsWinding[3].x = 130;
lpPointsWinding[3].y = 40; //{130,40}; lpPointsWinding[3].y = 40; //{130,40};
lpPointsWinding[4].x = 210; lpPointsWinding[4].x = 210;
lpPointsWinding[4].y = 40; //{210,40}; lpPointsWinding[4].y = 40; //{210,40};
*/
OldPen = (HPEN)SelectObject(hdc, BluePen);
OldBrush = (HBRUSH)SelectObject(hdc, RedBrush);
OldPen = (HPEN)SelectObject(Desktop, BluePen); Mode = GetPolyFillMode(hdc);
OldBrush = (HBRUSH)SelectObject(Desktop, RedBrush);
Mode = GetPolyFillMode(Desktop); SetPolyFillMode(hdc, ALTERNATE);
Polygon(hdc,PointsAlternate,sizeof(PointsAlternate)/sizeof(PointsAlternate[0]));
SetPolyFillMode(Desktop, ALTERNATE); SetPolyFillMode(hdc, WINDING);
Polygon(Desktop,lpPointsAlternate,5); Polygon(hdc,PointsWinding,sizeof(PointsWinding)/sizeof(PointsWinding[0]));
SetPolyFillMode(Desktop, WINDING); Polygon(hdc,Tri1,sizeof(Tri1)/sizeof(Tri1[0]));
Polygon(Desktop,lpPointsWinding,5); Polygon(hdc,Tri2,sizeof(Tri2)/sizeof(Tri2[0]));
//cleanup
SetPolyFillMode(Desktop, Mode);
SelectObject(Desktop, OldPen);
SelectObject(Desktop, OldBrush);
DeleteObject(BluePen);
DeleteObject(RedBrush);
Rectangle ( hdc, 3, 15, 7, 20 );
//cleanup
SetPolyFillMode(hdc, Mode);
DeleteObject ( SelectObject(hdc, OldPen) );
DeleteObject ( SelectObject(hdc, OldBrush) );
} }
void shaptest( HDC DevCtx ){ void shaptest( HDC hdc )
HDC Desktop, MyDC, DC24; {
HPEN RedPen, GreenPen, BluePen, WhitePen;
HBITMAP MyBitmap, DIB24;
HFONT hf, tf;
BITMAPINFOHEADER BitInf;
BITMAPINFO BitPalInf;
HRGN hRgn1, hRgn2, hRgn3;
HBRUSH BlueBrush, DefBrush;
int sec,Xmod,Ymod;
char tbuf[5];
BlueBrush = CreateSolidBrush( RGB(0, 0, 0xff) );
DefBrush = SelectObject( DevCtx, BlueBrush );
SelectObject( DevCtx, DefBrush );
DeleteObject( BlueBrush );
// Create a blue pen and select it into the DC
BluePen = CreatePen(PS_SOLID, 8, RGB(0, 0, 0xff));
SelectObject(DevCtx, BluePen);
//Test the Polygon routine. //Test the Polygon routine.
PolygonTest(DevCtx); PolygonTest(hdc);
} }
@ -116,8 +121,8 @@ WinMain(HINSTANCE hInstance,
wc.lpfnWndProc = MainWndProc; wc.lpfnWndProc = MainWndProc;
wc.style = CS_VREDRAW | CS_HREDRAW; wc.style = CS_VREDRAW | CS_HREDRAW;
wc.hInstance = hInstance; wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hIcon = (HICON)LoadIcon(NULL, (LPCTSTR)IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hCursor = (HCURSOR)LoadCursor(NULL, (LPCTSTR)IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH); wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
wc.lpszMenuName = NULL; wc.lpszMenuName = NULL;
wc.cbClsExtra = 0; wc.cbClsExtra = 0;
@ -125,7 +130,7 @@ WinMain(HINSTANCE hInstance,
if (RegisterClass(&wc) == 0) if (RegisterClass(&wc) == 0)
{ {
fprintf(stderr, "RegisterClass failed (last error 0x%X)\n", fprintf(stderr, "RegisterClass failed (last error 0x%X)\n",
GetLastError()); (unsigned int)GetLastError());
return(1); return(1);
} }
@ -143,7 +148,7 @@ WinMain(HINSTANCE hInstance,
if (hWnd == NULL) if (hWnd == NULL)
{ {
fprintf(stderr, "CreateWindow failed (last error 0x%X)\n", fprintf(stderr, "CreateWindow failed (last error 0x%X)\n",
GetLastError()); (unsigned int)GetLastError());
return(1); return(1);
} }
@ -166,27 +171,25 @@ WinMain(HINSTANCE hInstance,
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{ {
PAINTSTRUCT ps; PAINTSTRUCT ps;
HDC hDC; HDC hDC;
RECT clr, wir;
char spr[100], sir[100];
switch(msg) switch(msg)
{ {
case WM_PAINT: case WM_PAINT:
hDC = BeginPaint(hWnd, &ps); hDC = BeginPaint(hWnd, &ps);
shaptest( hDC ); shaptest( hDC );
EndPaint(hWnd, &ps); EndPaint(hWnd, &ps);
break; break;
case WM_DESTROY: case WM_DESTROY:
PostQuitMessage(0); PostQuitMessage(0);
break; break;
default: default:
return DefWindowProc(hWnd, msg, wParam, lParam); return DefWindowProc(hWnd, msg, wParam, lParam);
} }
return 0; return 0;
} }

View file

@ -3,6 +3,6 @@
BOOL STDCALL FillSolid (PSURFOBJ Surface, PRECTL Dimensions, ULONG iColor); BOOL STDCALL FillSolid (PSURFOBJ Surface, PRECTL Dimensions, ULONG iColor);
BOOL STDCALL FillPolygon_ALTERNATE (PDC dc, PSURFOBJ SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, INT Count, RECTL BoundRect); BOOL STDCALL FillPolygon_ALTERNATE (PDC dc, PSURFOBJ SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, INT Count, RECTL BoundRect);
BOOL STDCALL FillPolygon_WINDING (PSURFOBJ SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, INT Count, RECTL BoundRect); BOOL STDCALL FillPolygon_WINDING (PDC dc, PSURFOBJ SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, INT Count, RECTL BoundRect);
#endif /* __WIN32K_PAINT_H */ #endif /* __WIN32K_PAINT_H */

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: fillshap.c,v 1.21 2003/07/14 09:43:11 gvg Exp $ */ /* $Id: fillshap.c,v 1.22 2003/08/15 18:51:32 royce Exp $ */
#undef WIN32_LEAN_AND_MEAN #undef WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
@ -83,23 +83,24 @@ W32kPie(HDC hDC,
//even-numbered polygon sides on each scan line. That is, GDI fills the area between the //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. //first and second side, between the third and fourth side, and so on.
extern BOOL FillPolygon_ALTERNATE(PDC dc, extern BOOL FillPolygon_ALTERNATE(PDC dc,
SURFOBJ *SurfObj, SURFOBJ *SurfObj,
PBRUSHOBJ BrushObj, PBRUSHOBJ BrushObj,
MIX RopMode, MIX RopMode,
CONST PPOINT Points, CONST PPOINT Points,
int Count, int Count,
RECTL BoundRect); RECTL BoundRect);
//WINDING Selects winding mode (fills any region with a nonzero winding value). //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. //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. //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. //The direction of each edge of the polygon is important.
extern BOOL FillPolygon_WINDING(SURFOBJ *SurfObj, extern BOOL FillPolygon_WINDING(PDC dc,
PBRUSHOBJ BrushObj,MIX RopMode, SURFOBJ *SurfObj,
CONST PPOINT Points, PBRUSHOBJ BrushObj,MIX RopMode,
int Count, CONST PPOINT Points,
RECTL BoundRect); int Count,
RECTL BoundRect);
#endif #endif
//This implementation is blatantly ripped off from W32kRectangle //This implementation is blatantly ripped off from W32kRectangle
@ -122,7 +123,7 @@ W32kPolygon(HDC hDC,
DPRINT("In W32kPolygon()\n"); DPRINT("In W32kPolygon()\n");
if (NULL == dc || NULL == Points || Count < 2) if (NULL == dc || NULL == UnsafePoints || Count < 2)
{ {
SetLastWin32Error(ERROR_INVALID_PARAMETER); SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE; return FALSE;
@ -154,22 +155,22 @@ W32kPolygon(HDC hDC,
//ei not yet implemented ASSERT(RectBounds); //ei not yet implemented ASSERT(RectBounds);
if (PATH_IsPathOpen(dc->w.path)) if (PATH_IsPathOpen(dc->w.path))
{ {
ret = PATH_Polygon(hDC, Points, Count); ret = PATH_Polygon(hDC, Points, Count);
} }
else else
{ {
/* Get the current pen. */ /* Get the current pen. */
pen = (PENOBJ*) GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC); pen = (PENOBJ*) GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC);
ASSERT(pen); ASSERT(pen);
OutBrushObj = (PBRUSHOBJ) PenToBrushObj(dc, pen); OutBrushObj = (PBRUSHOBJ) PenToBrushObj(dc, pen);
GDIOBJ_UnlockObj(dc->w.hPen, GO_PEN_MAGIC); GDIOBJ_UnlockObj(dc->w.hPen, GO_PEN_MAGIC);
DestRect.left = Points[0].x; DestRect.left = Points[0].x;
DestRect.right = Points[0].x; DestRect.right = Points[0].x;
DestRect.top = Points[0].y; DestRect.top = Points[0].y;
DestRect.bottom = Points[0].y; DestRect.bottom = Points[0].y;
for (CurrentPoint = 1; CurrentPoint < Count; ++CurrentPoint) for (CurrentPoint = 1; CurrentPoint < Count; ++CurrentPoint)
{ {
DestRect.left = MIN(DestRect.left, Points[CurrentPoint].x); DestRect.left = MIN(DestRect.left, Points[CurrentPoint].x);
@ -181,19 +182,20 @@ W32kPolygon(HDC hDC,
/* Now fill the polygon with the current brush. */ /* Now fill the polygon with the current brush. */
FillBrushObj = (BRUSHOBJ*) GDIOBJ_LockObj(dc->w.hBrush, GO_BRUSH_MAGIC); FillBrushObj = (BRUSHOBJ*) GDIOBJ_LockObj(dc->w.hBrush, GO_BRUSH_MAGIC);
/* determine the fill mode to fill the polygon. */ /* determine the fill mode to fill the polygon. */
#if 1
if (WINDING == dc->w.polyFillMode) if (WINDING == dc->w.polyFillMode)
{ {
ret = FillPolygon_WINDING(SurfObj, FillBrushObj, dc->w.ROPmode, Points, Count, DestRect); ret = FillPolygon_WINDING(dc, SurfObj, FillBrushObj, dc->w.ROPmode, Points, Count, DestRect);
} }
else /* default */ else /* default */
{ {
ret = FillPolygon_ALTERNATE(dc, SurfObj, FillBrushObj, dc->w.ROPmode, Points, Count, DestRect); ret = FillPolygon_ALTERNATE(dc, SurfObj, FillBrushObj, dc->w.ROPmode, Points, Count, DestRect);
} }
#endif
// Draw the Polygon Edges with the current pen // Draw the Polygon Edges with the current pen
for (CurrentPoint = 0; CurrentPoint < Count; ++CurrentPoint) for (CurrentPoint = 0; CurrentPoint < Count; ++CurrentPoint)
{ {
POINT To, From, Next; POINT To, From; //, Next;
/* Let CurrentPoint be i /* Let CurrentPoint be i
* if i+1 > Count, Draw a line from Points[i] to Points[0] * if i+1 > Count, Draw a line from Points[i] to Points[0]
@ -209,39 +211,6 @@ W32kPolygon(HDC hDC,
To = Points[CurrentPoint + 1]; To = Points[CurrentPoint + 1];
} }
/* Special handling of lower right corner of a rectangle. If we
* don't treat it specially, it will end up looking like this:
*
* *
* *
* *
* *********
*/
if (3 < Count)
{
if (Count <= CurrentPoint + 2)
{
Next = Points[CurrentPoint + 2 - Count];
}
else
{
Next = Points[CurrentPoint + 2];
}
if (From.x == To.x &&
From.y <= To.y &&
To.y == Next.y &&
Next.x <= To.x)
{
To.y++;
}
else if (From.y == To.y &&
From.x <= To.x &&
To.x == Next.x &&
Next.y <= To.y)
{
To.x++;
}
}
DPRINT("Polygon Making line from (%d,%d) to (%d,%d)\n", From.x, From.y, To.x, To.y ); DPRINT("Polygon Making line from (%d,%d) to (%d,%d)\n", From.x, From.y, To.x, To.y );
ret = IntEngLineTo(SurfObj, ret = IntEngLineTo(SurfObj,
dc->CombinedClip, dc->CombinedClip,
@ -254,6 +223,17 @@ W32kPolygon(HDC hDC,
dc->w.ROPmode); /* MIX */ dc->w.ROPmode); /* MIX */
} }
#if 0
/* determine the fill mode to fill the polygon. */
if (WINDING == dc->w.polyFillMode)
{
ret = FillPolygon_WINDING(dc, SurfObj, FillBrushObj, dc->w.ROPmode, Points, Count, DestRect);
}
else /* default */
{
ret = FillPolygon_ALTERNATE(dc, SurfObj, FillBrushObj, dc->w.ROPmode, Points, Count, DestRect);
}
#endif
GDIOBJ_UnlockObj(dc->w.hBrush, GO_BRUSH_MAGIC); GDIOBJ_UnlockObj(dc->w.hBrush, GO_BRUSH_MAGIC);
} }
@ -297,9 +277,12 @@ W32kRectangle(HDC hDC,
RectBounds = GDIOBJ_LockObj(dc->w.hGCClipRgn, GO_REGION_MAGIC); RectBounds = GDIOBJ_LockObj(dc->w.hGCClipRgn, GO_REGION_MAGIC);
//ei not yet implemented ASSERT(RectBounds); //ei not yet implemented ASSERT(RectBounds);
if(PATH_IsPathOpen(dc->w.path)) { if(PATH_IsPathOpen(dc->w.path))
{
ret = PATH_Rectangle(hDC, LeftRect, TopRect, RightRect, BottomRect); ret = PATH_Rectangle(hDC, LeftRect, TopRect, RightRect, BottomRect);
} else { }
else
{
// Draw the rectangle with the current pen // Draw the rectangle with the current pen
pen = (PENOBJ*) GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC); pen = (PENOBJ*) GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC);
ASSERT(pen); ASSERT(pen);

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: polyfill.c,v 1.6 2003/08/13 00:50:25 royce Exp $ /* $Id: polyfill.c,v 1.7 2003/08/15 18:51:32 royce Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -47,33 +47,44 @@
*/ */
typedef struct _tagPFILL_EDGE typedef struct _tagPFILL_EDGE
{ {
/*Basic line information*/ /*Basic line information*/
int FromX; int FromX;
int FromY; int FromY;
int ToX; int ToX;
int ToY; int ToY;
int dx; int dx;
int dy; int dy;
int MinX; int MinX;
int MaxX; int MaxX;
int MinY; int MinY;
int MaxY; int MaxY;
/*Active Edge List information*/
int XIntercept;
int ErrorTerm;
int ErrorTermAdjUp;
int ErrorTermAdjDown;
int XPerY;
int Direction;
/* The next edge in the Edge List*/ /*Active Edge List information*/
struct _tagPFILL_EDGE * pNext; int XIntercept;
int Error;
int ErrorInc;
int ErrorMax;
int XPerY;
int XDirection;
int YDirection; // used for Winding
/* The next edge in the Edge List*/
struct _tagPFILL_EDGE * pNext;
} PFILL_EDGE, *PPFILL_EDGE; } PFILL_EDGE, *PPFILL_EDGE;
typedef PPFILL_EDGE PFILL_EDGE_LIST; typedef PPFILL_EDGE PFILL_EDGE_LIST;
/*static void DEBUG_PRINT_EDGELIST(PFILL_EDGE_LIST list) static
inline
int
abs ( int a )
{
return a < 0 ? -a : a;
}
/*static
void
DEBUG_PRINT_EDGELIST(PFILL_EDGE_LIST list)
{ {
PPFILL_EDGE pThis = list; PPFILL_EDGE pThis = list;
if (0 == list) if (0 == list)
@ -92,96 +103,101 @@ typedef PPFILL_EDGE PFILL_EDGE_LIST;
/* /*
** Hide memory clean up. ** Hide memory clean up.
*/ */
static void FASTCALL POLYGONFILL_DestroyEdge(PPFILL_EDGE pEdge) static
void
FASTCALL
POLYGONFILL_DestroyEdge(PPFILL_EDGE pEdge)
{ {
if (0 != pEdge) if (0 != pEdge)
EngFreeMem(pEdge); EngFreeMem(pEdge);
} }
/* /*
** Clean up a list. ** Clean up a list.
*/ */
static void FASTCALL POLYGONFILL_DestroyEdgeList(PFILL_EDGE_LIST list) static
void
FASTCALL
POLYGONFILL_DestroyEdgeList(PFILL_EDGE_LIST list)
{ {
PPFILL_EDGE pThis = 0; PPFILL_EDGE pThis = 0;
PPFILL_EDGE pNext = 0; PPFILL_EDGE pNext = 0;
pThis = list; pThis = list;
while (0 != pThis) while (0 != pThis)
{ {
//DPRINT("Destroying Edge\n"); //DPRINT("Destroying Edge\n");
pNext = pThis->pNext; pNext = pThis->pNext;
POLYGONFILL_DestroyEdge(pThis); POLYGONFILL_DestroyEdge(pThis);
pThis = pNext; pThis = pNext;
} }
} }
/* /*
** This makes and initiaizes an Edge struct for a line between two points. ** This makes and initiaizes an Edge struct for a line between two points.
*/ */
static PPFILL_EDGE FASTCALL POLYGONFILL_MakeEdge(POINT From, POINT To) static
PPFILL_EDGE
FASTCALL
POLYGONFILL_MakeEdge(POINT From, POINT To)
{ {
PPFILL_EDGE rc = (PPFILL_EDGE)EngAllocMem(FL_ZERO_MEMORY, sizeof(PFILL_EDGE), PFILL_EDGE_ALLOC_TAG); int absdx, absdy;
PPFILL_EDGE rc = (PPFILL_EDGE)EngAllocMem(FL_ZERO_MEMORY, sizeof(PFILL_EDGE), PFILL_EDGE_ALLOC_TAG);
if (0 != rc) if (0 == rc)
{ return NULL;
//DPRINT("Making Edge: (%d, %d) to (%d, %d)\n", From.x, From.y, To.x, To.y);
//Now Fill the struct.
rc->FromX = From.x;
rc->FromY = From.y;
rc->ToX = To.x;
rc->ToY = To.y;
rc->dx = To.x - From.x;
rc->dy = To.y - From.y;
rc->MinX = MIN(To.x, From.x);
rc->MaxX = MAX(To.x, From.x);
rc->MinY = MIN(To.y, From.y);
rc->MaxY = MAX(To.y, From.y);
if (rc->MinY == To.y) //DPRINT ("Making Edge: (%d, %d) to (%d, %d)\n", From.x, From.y, To.x, To.y);
rc->XIntercept = To.x; //Now Fill the struct.
else if ( To.y < From.y )
rc->XIntercept = From.x; {
rc->FromX = To.x;
rc->FromY = To.y;
rc->ToX = From.x;
rc->ToY = From.y;
rc->YDirection = -1;
}
else
{
rc->FromX = From.x;
rc->FromY = From.y;
rc->ToX = To.x;
rc->ToY = To.y;
rc->YDirection = 1;
}
rc->ErrorTermAdjDown = rc->dy; rc->dx = rc->ToX - rc->FromX;
rc->Direction = (rc->dx < 0)?(-1):(1); rc->dy = rc->ToY - rc->FromY;
absdx = abs(rc->dx);
if (rc->dx >= 0) /*edge goes l to r*/ absdy = abs(rc->dy);
{ rc->MinX = MIN(To.x, From.x);
rc->ErrorTerm = 0; rc->MaxX = MAX(To.x, From.x);
} rc->MinY = MIN(To.y, From.y);
else/*edge goes r to l*/ rc->MaxY = MAX(To.y, From.y);
{
rc->ErrorTerm = -rc->dy +1;
}
/*Now which part of the slope is greater?*/ if (rc->MinY == To.y)
if (rc->dy == 0) rc->XIntercept = To.x;
{ else
rc->XPerY = 0; rc->XIntercept = From.x;
rc->ErrorTermAdjUp = 0;
} rc->ErrorMax = absdy;
else if (rc->dy >= rc->dx) rc->ErrorInc = absdx;
{
rc->XPerY = 0; rc->Error = rc->ErrorMax / 2;
rc->ErrorTermAdjUp = rc->dx;
} rc->XDirection = (rc->dx < 0)?(-1):(1);
else
{ rc->pNext = 0;
rc->XPerY = rc->dx / rc->dy;
rc->ErrorTermAdjUp = rc->dx % rc->dy; DPRINT ("MakeEdge (%i,%i)->(%i,%i) d=(%i,%i) dir=%i err=%i max=%i\n",
} From.x, From.y, To.x, To.y, rc->dx, rc->dy, rc->Direction, rc->Error, rc->ErrorMax );
rc->pNext = 0; return rc;
}
return rc;
} }
/* /*
** My Edge comparison routine. ** My Edge comparison routine.
** This is for scan converting polygon fill. ** This is for scan converting polygon fill.
** Fist sort by MinY, then Minx, then slope. ** First sort by MinY, then Minx, then slope.
** **
** This comparison will help us determine which ** This comparison will help us determine which
** lines will become active first when scanning from ** lines will become active first when scanning from
@ -192,107 +208,115 @@ static PPFILL_EDGE FASTCALL POLYGONFILL_MakeEdge(POINT From, POINT To)
** Zero element1 = element2 ** Zero element1 = element2
** Positive integer element1 > element2 ** Positive integer element1 > element2
*/ */
static INT FASTCALL PFILL_EDGE_Compare(PPFILL_EDGE Edge1, PPFILL_EDGE Edge2) static
INT
FASTCALL
PFILL_EDGE_Compare(PPFILL_EDGE Edge1, PPFILL_EDGE Edge2)
{ {
//DPRINT("In PFILL_EDGE_Compare()\n"); //DPRINT("In PFILL_EDGE_Compare()\n");
if (Edge1->MinY == Edge2->MinY) if (Edge1->MinY == Edge2->MinY)
{
//DPRINT("In PFILL_EDGE_Compare() MinYs are equal\n");
if (Edge1->MinX == Edge2->MinX)
{ {
//DPRINT("In PFILL_EDGE_Compare() MinYs are equal\n"); if (0 == Edge2->dx || 0 == Edge1->dx)
if (Edge1->MinX == Edge2->MinX) {
{ return Edge1->dx - Edge2->dx;
if (0 == Edge2->dx || 0 == Edge1->dx) }
{ else
return Edge1->dx - Edge2->dx; {
} return (Edge1->dy/Edge1->dx) - (Edge2->dy/Edge2->dx);
else }
{
return (Edge1->dy/Edge1->dx) - (Edge2->dy/Edge2->dx);
}
}
else
{
return Edge1->MinX - Edge2->MinX;
}
} }
//DPRINT("In PFILL_EDGE_Compare() returning: %d\n",Edge1->MinY - Edge2->MinY); else
return Edge1->MinY - Edge2->MinY; {
return Edge1->MinX - Edge2->MinX;
}
}
//DPRINT("In PFILL_EDGE_Compare() returning: %d\n",Edge1->MinY - Edge2->MinY);
return Edge1->MinY - Edge2->MinY;
} }
/* /*
** Insert an edge into a list keeping the list in order. ** Insert an edge into a list keeping the list in order.
*/ */
static void FASTCALL POLYGONFILL_ListInsert(PFILL_EDGE_LIST *list, PPFILL_EDGE NewEdge) static
void
FASTCALL
POLYGONFILL_ListInsert(PFILL_EDGE_LIST *list, PPFILL_EDGE NewEdge)
{ {
PPFILL_EDGE pThis; PPFILL_EDGE pThis;
if (0 != list && 0 != NewEdge) if (0 != list && 0 != NewEdge)
{
pThis = *list;
//DPRINT("In POLYGONFILL_ListInsert()\n");
/*
** First lets check to see if we have a new smallest value.
*/
if (0 < PFILL_EDGE_Compare(pThis, NewEdge))
{ {
pThis = *list; NewEdge->pNext = pThis;
//DPRINT("In POLYGONFILL_ListInsert()\n"); *list = NewEdge;
/* return;
** First lets check to see if we have a new smallest value.
*/
if (0 < PFILL_EDGE_Compare(pThis, NewEdge))
{
NewEdge->pNext = pThis;
*list = NewEdge;
return;
}
/*
** Ok, now scan to the next spot to put this item.
*/
while (0 > PFILL_EDGE_Compare(pThis, NewEdge))
{
if (0 == pThis->pNext)
break;
pThis = pThis->pNext;
}
NewEdge->pNext = pThis->pNext;
pThis->pNext = NewEdge;
//DEBUG_PRINT_EDGELIST(*list);
} }
/*
** Ok, now scan to the next spot to put this item.
*/
while (0 > PFILL_EDGE_Compare(pThis, NewEdge))
{
if (0 == pThis->pNext)
break;
pThis = pThis->pNext;
}
NewEdge->pNext = pThis->pNext;
pThis->pNext = NewEdge;
//DEBUG_PRINT_EDGELIST(*list);
}
} }
/* /*
** Create a list of edges for a list of points. ** Create a list of edges for a list of points.
*/ */
static PFILL_EDGE_LIST FASTCALL POLYGONFILL_MakeEdgeList(PPOINT Points, int Count) static
PFILL_EDGE_LIST
FASTCALL
POLYGONFILL_MakeEdgeList(PPOINT Points, int Count)
{ {
int CurPt = 0; int CurPt = 0;
int SeqNum = 0; int SeqNum = 0;
PPFILL_EDGE rc = 0; PPFILL_EDGE rc = 0;
PPFILL_EDGE NextEdge = 0; PPFILL_EDGE NextEdge = 0;
if (0 != Points && 2 <= Count)
{
//Establish the list with the first two points.
rc = POLYGONFILL_MakeEdge(Points[0],Points[1]);
if (0 == rc) return rc;
for (CurPt = 1; CurPt < Count; ++CurPt,++SeqNum) if ( 0 == Points || 2 > Count )
{ return rc;
if (CurPt == Count - 1)
{ //Establish the list with the first two points.
NextEdge = POLYGONFILL_MakeEdge(Points[CurPt],Points[0]); rc = POLYGONFILL_MakeEdge ( Points[0], Points[1] );
} if (0 == rc) return rc;
else
{ for ( CurPt = 1; CurPt < Count; ++CurPt,++SeqNum )
NextEdge = POLYGONFILL_MakeEdge(Points[CurPt],Points[CurPt + 1]); {
} if (CurPt == Count - 1 )
if (0 != NextEdge) {
{ NextEdge = POLYGONFILL_MakeEdge(Points[CurPt],Points[0]);
POLYGONFILL_ListInsert(&rc, NextEdge); }
} else
else {
{ NextEdge = POLYGONFILL_MakeEdge(Points[CurPt],Points[CurPt + 1]);
DPRINT("Out Of MEMORY!! NextEdge = 0\n"); }
} if (0 != NextEdge)
} {
} POLYGONFILL_ListInsert(&rc, NextEdge);
return rc; }
else
{
DPRINT1("Out Of MEMORY!! NextEdge = 0\n");
}
}
return rc;
} }
@ -302,28 +326,27 @@ static PFILL_EDGE_LIST FASTCALL POLYGONFILL_MakeEdgeList(PPOINT Points, int Coun
** for scanline Scanline. ** for scanline Scanline.
**TODO: Get rid of this floating point arithmetic **TODO: Get rid of this floating point arithmetic
*/ */
static void FASTCALL POLYGONFILL_UpdateScanline(PPFILL_EDGE pEdge, int Scanline) static
void
FASTCALL
POLYGONFILL_UpdateScanline(PPFILL_EDGE pEdge, int Scanline)
{ {
if ( 0 == pEdge->dy )
int Coord = 0; return;
float XCoord = 0;
if (0 == pEdge->dy) return;
XCoord = (Scanline*pEdge->dx - pEdge->FromY*pEdge->dx)/pEdge->dy + pEdge->FromX; if ( pEdge->ErrorMax )
Coord = XCoord + 0.5; {
pEdge->Error += pEdge->ErrorInc;
//DPRINT("Line (%d, %d) to (%d, %d) intersects scanline %d at %d\n", if ( pEdge->Error >= pEdge->ErrorMax )
// pEdge->FromX, pEdge->FromY, pEdge->ToX, pEdge->ToY, Scanline, Coord);
pEdge->XIntercept = Coord;
/*pEdge->XIntercept += pEdge->XPerY;
if ((pEdge->ErrorTerm += pEdge->ErrorTermAdjUp) > 0)
{ {
pEdge->XIntercept += pEdge->Direction; int steps = pEdge->Error / pEdge->ErrorMax;
pEdge->ErrorTerm -= pEdge->ErrorTermAdjDown; pEdge->XIntercept += steps * pEdge->XDirection;
}*/ pEdge->Error -= steps * pEdge->ErrorMax;
}
}
DPRINT ("Line (%d, %d) to (%d, %d) intersects scanline %d at %d\n",
pEdge->FromX, pEdge->FromY, pEdge->ToX, pEdge->ToY, Scanline, pEdge->XIntercept );
} }
/* /*
@ -333,197 +356,249 @@ static void FASTCALL POLYGONFILL_UpdateScanline(PPFILL_EDGE pEdge, int Scanline)
** **
** Note: once an edge is no longer active, it is deleted. ** Note: once an edge is no longer active, it is deleted.
*/ */
static void FASTCALL POLYGONFILL_AECInsertInOrder(PFILL_EDGE_LIST *list, PPFILL_EDGE pEdge) static
void
FASTCALL
POLYGONFILL_AECInsertInOrder(PFILL_EDGE_LIST *list, PPFILL_EDGE pEdge)
{ {
BOOL Done = FALSE; BOOL Done = FALSE;
PPFILL_EDGE pThis = 0; PPFILL_EDGE pThis = 0;
PPFILL_EDGE pPrev = 0; PPFILL_EDGE pPrev = 0;
pThis = *list; pThis = *list;
while(0 != pThis && !Done) while(0 != pThis && !Done)
{
/*pEdge goes before pThis*/
if (pThis->XIntercept > pEdge->XIntercept)
{ {
/*pEdge goes before pThis*/ if (*list == pThis)
if (pThis->XIntercept > pEdge->XIntercept) {
{ *list = pEdge;
if (*list == pThis) }
{ else
*list = pEdge; {
} pPrev->pNext = pEdge;
else }
{ pEdge->pNext = pThis;
pPrev->pNext = pEdge; Done = TRUE;
}
pEdge->pNext = pThis;
Done = TRUE;
}
pPrev = pThis;
pThis = pThis->pNext;
} }
pPrev = pThis;
pThis = pThis->pNext;
}
} }
/* /*
** This routine reorders the Active Edge collection (list) after all ** This routine reorders the Active Edge collection (list) after all
** the now inactive edges have been removed. ** the now inactive edges have been removed.
*/ */
static void FASTCALL POLYGONFILL_AECReorder(PFILL_EDGE_LIST *AEC) static
void
FASTCALL
POLYGONFILL_AECReorder(PFILL_EDGE_LIST *AEC)
{ {
PPFILL_EDGE pThis = 0; PPFILL_EDGE pThis = 0;
PPFILL_EDGE pPrev = 0; PPFILL_EDGE pPrev = 0;
PPFILL_EDGE pTarg = 0; PPFILL_EDGE pTarg = 0;
pThis = *AEC; pThis = *AEC;
while (0 != pThis)
{
/*We are at the end of the list*/
if (0 == pThis->pNext)
{
return;
}
/*If the next item is out of order, pull it from the list and while (0 != pThis)
re-insert it, and don't advance pThis.*/ {
if (pThis->XIntercept > pThis->pNext->XIntercept) /*We are at the end of the list*/
{ if ( 0 == pThis->pNext )
pTarg = pThis->pNext; return;
pThis->pNext = pTarg->pNext;
pTarg->pNext = 0; /*If the next item is out of order, pull it from the list and
POLYGONFILL_AECInsertInOrder(AEC, pTarg); re-insert it, and don't advance pThis.*/
} if (pThis->XIntercept > pThis->pNext->XIntercept)
else/*In order, advance pThis*/ {
{ pTarg = pThis->pNext;
pPrev = pThis; pThis->pNext = pTarg->pNext;
pThis = pThis->pNext; pTarg->pNext = 0;
} POLYGONFILL_AECInsertInOrder(AEC, pTarg);
} }
else/*In order, advance pThis*/
{
pPrev = pThis;
pThis = pThis->pNext;
}
}
} }
/* /*
** This method updates the Active edge collection for the scanline Scanline. ** This method updates the Active edge collection for the scanline Scanline.
*/ */
static void STDCALL POLYGONFILL_UpdateActiveEdges(int Scanline, PFILL_EDGE_LIST *GEC, PFILL_EDGE_LIST *AEC) static
void
STDCALL
POLYGONFILL_UpdateActiveEdges(int Scanline, PFILL_EDGE_LIST *GEC, PFILL_EDGE_LIST *AEC)
{ {
PPFILL_EDGE pThis = 0; PPFILL_EDGE pThis = 0;
PPFILL_EDGE pAECLast = 0; PPFILL_EDGE pAECLast = 0;
PPFILL_EDGE pPrev = 0; PPFILL_EDGE pPrev = 0;
DPRINT("In POLYGONFILL_UpdateActiveEdges() Scanline: %d\n", Scanline); DPRINT("In POLYGONFILL_UpdateActiveEdges() Scanline: %d\n", Scanline);
/*First scan through GEC and look for any edges that have become active*/ /*First scan through GEC and look for any edges that have become active*/
pThis = *GEC;
while (0 != pThis && pThis->MinY <= Scanline)
{
//DPRINT("Moving Edge to AEC\n");
/*Remove the edge from GEC and put it into AEC*/
if (pThis->MinY <= Scanline)
{
/*Always peel off the front of the GEC*/
*GEC = pThis->pNext;
/*Now put this edge at the end of AEC*/
if (0 == *AEC)
{
*AEC = pThis;
pThis->pNext = 0;
pAECLast = pThis;
}
else if(0 == pAECLast)
{
pAECLast = *AEC;
while(0 != pAECLast->pNext)
{
pAECLast = pAECLast->pNext;
}
pAECLast->pNext = pThis;
pThis->pNext = 0;
pAECLast = pThis;
}
else
{
pAECLast->pNext = pThis;
pThis->pNext = 0;
pAECLast = pThis;
}
}
pThis = *GEC; pThis = *GEC;
while (0 != pThis && pThis->MinY <= Scanline) }
/*Now remove any edges in the AEC that are no longer active and Update the XIntercept in the AEC*/
pThis = *AEC;
while (0 != pThis)
{
/*First check to see if this item is deleted*/
if (pThis->MaxY <= Scanline)
{ {
//DPRINT("Moving Edge to AEC\n"); //DPRINT("Removing Edge from AEC\n");
/*Remove the edge from GEC and put it into AEC*/ if (0 == pPrev)/*First element in the list*/
if (pThis->MinY <= Scanline) {
{ *AEC = pThis->pNext;
/*Always peel off the front of the GEC*/ }
*GEC = pThis->pNext; else
{
/*Now put this edge at the end of AEC*/ pPrev->pNext = pThis->pNext;
if (0 == *AEC) }
{ POLYGONFILL_DestroyEdge(pThis);
*AEC = pThis;
pThis->pNext = 0;
pAECLast = pThis;
}
else if(0 == pAECLast)
{
pAECLast = *AEC;
while(0 != pAECLast->pNext)
{
pAECLast = pAECLast->pNext;
}
pAECLast->pNext = pThis;
pThis->pNext = 0;
pAECLast = pThis;
}
else
{
pAECLast->pNext = pThis;
pThis->pNext = 0;
pAECLast = pThis;
}
}
pThis = *GEC;
} }
/*Now remove any edges in the AEC that are no longer active and Update the XIntercept in the AEC*/ else/*Otherwise, update the scanline*/
pThis = *AEC;
while (0 != pThis)
{ {
/*First check to see if this item is deleted*/ POLYGONFILL_UpdateScanline(pThis, Scanline);
if (pThis->MaxY <= Scanline) pPrev = pThis;
{
//DPRINT("Removing Edge from AEC\n");
if (0 == pPrev)/*First element in the list*/
{
*AEC = pThis->pNext;
}
else
{
pPrev->pNext = pThis->pNext;
}
POLYGONFILL_DestroyEdge(pThis);
}
else/*Otherwise, update the scanline*/
{
POLYGONFILL_UpdateScanline(pThis, Scanline);
pPrev = pThis;
}
/*List Upkeep*/
if (0 == pPrev)/*First element in the list*/
{
pThis = *AEC;
}
else
{
pThis = pPrev->pNext;
}
} }
/*Last re Xintercept order the AEC*/ /*List Upkeep*/
POLYGONFILL_AECReorder(AEC); if (0 == pPrev)/*First element in the list*/
{
pThis = *AEC;
}
else
{
pThis = pPrev->pNext;
}
}
/*Last re Xintercept order the AEC*/
POLYGONFILL_AECReorder(AEC);
} }
/* /*
** This method fills the portion of the polygon that intersects with the scanline ** This method fills the portion of the polygon that intersects with the scanline
** Scanline. ** Scanline.
*/ */
static void STDCALL POLYGONFILL_FillScanLine(PDC dc, int ScanLine, PFILL_EDGE_LIST ActiveEdges, SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX RopMode) static
void
STDCALL
POLYGONFILL_FillScanLineAlternate(PDC dc, int ScanLine, PFILL_EDGE_LIST ActiveEdges, SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX RopMode)
{ {
BOOL OnOdd = TRUE; BOOL OnOdd = TRUE;
RECTL BoundRect; RECTL BoundRect;
int XInterceptOdd,XInterceptEven,ret; int XInterceptOdd,XInterceptEven,ret;
PPFILL_EDGE pThis = ActiveEdges; PPFILL_EDGE pThis = ActiveEdges;
while (NULL != pThis)
{
if (OnOdd)
{
XInterceptOdd = pThis->XIntercept;
OnOdd = FALSE;
}
else
{
BoundRect.top = ScanLine - 1;
BoundRect.bottom = ScanLine + 1;
BoundRect.left = XInterceptOdd - 2;
BoundRect.right = XInterceptEven;
XInterceptEven = pThis->XIntercept; while (NULL != pThis)
DPRINT("Fill Line (%d, %d) to (%d, %d)\n",XInterceptOdd - 1, ScanLine, XInterceptEven - 1, ScanLine); {
ret = IntEngLineTo(SurfObj, if (OnOdd)
dc->CombinedClip, {
BrushObj, XInterceptOdd = pThis->XIntercept;
XInterceptOdd - 1, OnOdd = FALSE;
ScanLine,
XInterceptEven - 1,
ScanLine,
&BoundRect, /* Bounding rectangle */
RopMode); /* MIX */
OnOdd = TRUE;
}
pThis = pThis->pNext;
} }
else
{
XInterceptEven = pThis->XIntercept+1;
if ( XInterceptEven > XInterceptOdd )
{
BoundRect.top = ScanLine;
BoundRect.bottom = ScanLine + 1;
BoundRect.left = XInterceptOdd;
BoundRect.right = XInterceptEven;
DPRINT ("Fill Line (%d, %d) to (%d, %d)\n",XInterceptOdd, ScanLine, XInterceptEven, ScanLine);
ret = IntEngLineTo( SurfObj,
dc->CombinedClip,
BrushObj,
XInterceptOdd,
ScanLine,
XInterceptEven,
ScanLine,
&BoundRect, /* Bounding rectangle */
RopMode); /* MIX */
}
OnOdd = TRUE;
}
pThis = pThis->pNext;
}
}
static
void
STDCALL
POLYGONFILL_FillScanLineWinding(PDC dc, int ScanLine, PFILL_EDGE_LIST ActiveEdges, SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX RopMode)
{
RECTL BoundRect;
int XPrevIntercept,XIntercept,ret;
PPFILL_EDGE pThis = ActiveEdges;
int winding = 0;
XPrevIntercept = pThis->XIntercept;
winding += pThis->YDirection;
pThis = pThis->pNext;
while (NULL != pThis)
{
XIntercept = pThis->XIntercept + 1;
if ( winding && XIntercept > XPrevIntercept )
{
BoundRect.top = ScanLine;
BoundRect.bottom = ScanLine + 1;
BoundRect.left = XPrevIntercept;
BoundRect.right = XIntercept;
DPRINT ("Fill Line (%d, %d) to (%d, %d)\n",XPrevIntercept, ScanLine, XIntercept, ScanLine);
ret = IntEngLineTo( SurfObj,
dc->CombinedClip,
BrushObj,
XPrevIntercept,
ScanLine,
XIntercept,
ScanLine,
&BoundRect, // Bounding rectangle
RopMode); // MIX
}
XPrevIntercept = XIntercept - 1;
winding += pThis->YDirection;
pThis = pThis->pNext;
}
} }
//ALTERNATE Selects alternate mode (fills the area between odd-numbered and even-numbered //ALTERNATE Selects alternate mode (fills the area between odd-numbered and even-numbered
@ -531,32 +606,32 @@ static void STDCALL POLYGONFILL_FillScanLine(PDC dc, int ScanLine, PFILL_EDGE_LI
//When the fill mode is ALTERNATE, GDI fills the area between odd-numbered and //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 //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. //first and second side, between the third and fourth side, and so on.
BOOL STDCALL FillPolygon_ALTERNATE(PDC dc, SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, int Count, RECTL BoundRect) BOOL
STDCALL
FillPolygon_ALTERNATE(PDC dc, SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, int Count, RECTL BoundRect)
{ {
PFILL_EDGE_LIST list = 0; PFILL_EDGE_LIST list = 0;
PFILL_EDGE_LIST ActiveEdges = 0; PFILL_EDGE_LIST ActiveEdges = 0;
int ScanLine; int ScanLine;
DPRINT("FillPolygon_ALTERNATE\n"); DPRINT("FillPolygon_ALTERNATE\n");
/* Create Edge List. */ /* Create Edge List. */
list = POLYGONFILL_MakeEdgeList(Points, Count); list = POLYGONFILL_MakeEdgeList(Points, Count);
/* DEBUG_PRINT_EDGELIST(list); */ /* DEBUG_PRINT_EDGELIST(list); */
if (NULL == list) if (NULL == list)
{ return FALSE;
return FALSE;
}
/* For each Scanline from BoundRect.bottom to BoundRect.top, /* For each Scanline from BoundRect.bottom to BoundRect.top,
* determine line segments to draw * determine line segments to draw
*/ */
for (ScanLine = BoundRect.top + 1; ScanLine < BoundRect.bottom ; ++ScanLine) for ( ScanLine = BoundRect.top + 1; ScanLine < BoundRect.bottom; ++ScanLine )
{ {
POLYGONFILL_UpdateActiveEdges(ScanLine, &list, &ActiveEdges); POLYGONFILL_UpdateActiveEdges(ScanLine, &list, &ActiveEdges);
/* DEBUG_PRINT_EDGELIST(ActiveEdges); */ /* DEBUG_PRINT_EDGELIST(ActiveEdges); */
POLYGONFILL_FillScanLine(dc, ScanLine, ActiveEdges, SurfObj, BrushObj, RopMode); POLYGONFILL_FillScanLineAlternate(dc, ScanLine, ActiveEdges, SurfObj, BrushObj, RopMode);
} }
/* Free Edge List. If any are left. */ /* Free Edge List. If any are left. */
POLYGONFILL_DestroyEdgeList(list); POLYGONFILL_DestroyEdgeList(list);
@ -567,10 +642,35 @@ BOOL STDCALL FillPolygon_ALTERNATE(PDC dc, SURFOBJ *SurfObj, PBRUSHOBJ BrushObj,
//When the fill mode is WINDING, GDI fills any region that has 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. //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. //The direction of each edge of the polygon is important.
BOOL STDCALL FillPolygon_WINDING(SURFOBJ *SurfObj, PBRUSHOBJ BrushObj,MIX RopMode, CONST PPOINT Points, int Count, RECTL BoundRect) BOOL
STDCALL
FillPolygon_WINDING(PDC dc, SURFOBJ *SurfObj, PBRUSHOBJ BrushObj,MIX RopMode, CONST PPOINT Points, int Count, RECTL BoundRect)
{ {
DPRINT("FillPolygon_WINDING\n"); PFILL_EDGE_LIST list = 0;
PFILL_EDGE_LIST ActiveEdges = 0;
int ScanLine;
return FALSE; DPRINT("FillPolygon_ALTERNATE\n");
/* Create Edge List. */
list = POLYGONFILL_MakeEdgeList(Points, Count);
/* DEBUG_PRINT_EDGELIST(list); */
if (NULL == list)
return FALSE;
/* For each Scanline from BoundRect.bottom to BoundRect.top,
* determine line segments to draw
*/
for ( ScanLine = BoundRect.top + 1; ScanLine < BoundRect.bottom; ++ScanLine )
{
POLYGONFILL_UpdateActiveEdges(ScanLine, &list, &ActiveEdges);
/* DEBUG_PRINT_EDGELIST(ActiveEdges); */
POLYGONFILL_FillScanLineWinding(dc, ScanLine, ActiveEdges, SurfObj, BrushObj, RopMode);
}
/* Free Edge List. If any are left. */
POLYGONFILL_DestroyEdgeList(list);
return TRUE;
} }
/* EOF */ /* EOF */