diff --git a/reactos/apps/tests/shaptest/makefile b/reactos/apps/tests/shaptest/makefile index 6af2d5ee4a7..9c4e81f7616 100644 --- a/reactos/apps/tests/shaptest/makefile +++ b/reactos/apps/tests/shaptest/makefile @@ -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 = ../../.. @@ -6,10 +6,12 @@ TARGET_NORC = yes TARGET_TYPE = program -TARGET_APPTYPE = console +TARGET_APPTYPE = windows TARGET_NAME = shaptest +TARGET_CFLAGS = -Wall -Werror + TARGET_SDKLIBS = kernel32.a gdi32.a TARGET_OBJECTS = $(TARGET_NAME).o diff --git a/reactos/apps/tests/shaptest/shaptest.c b/reactos/apps/tests/shaptest/shaptest.c index 3ef8e4dc61e..48a7ff6116e 100644 --- a/reactos/apps/tests/shaptest/shaptest.c +++ b/reactos/apps/tests/shaptest/shaptest.c @@ -15,90 +15,95 @@ HFONT tf; LRESULT WINAPI MainWndProc(HWND, UINT, WPARAM, LPARAM); -void __stdcall PolygonTest(HDC Desktop) +void PolygonTest ( HDC hdc ) { - HPEN BluePen; - HPEN OldPen; - HBRUSH RedBrush; - HBRUSH OldBrush; - POINT lpPointsAlternate[5]; - POINT lpPointsWinding[5]; - DWORD Mode; + HPEN BluePen, OldPen; + HBRUSH RedBrush, OldBrush; + DWORD Mode; + POINT PointsAlternate[] = + { + { 20, 80 }, + { 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 - BluePen = CreatePen(PS_SOLID, 3, RGB(0, 0, 0xff)); - RedBrush = CreateSolidBrush(RGB(0xff, 0, 0)); + //create a pen to draw the shape + BluePen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0xff)); + RedBrush = CreateSolidBrush(RGB(0xff, 0, 0)); - //initialize a set of points for alternate. - lpPointsAlternate[0].x = 20; - lpPointsAlternate[0].y = 80; //{20,80}; - lpPointsAlternate[1].x = 60; - lpPointsAlternate[1].y = 20; //{60,20}; - lpPointsAlternate[2].x = 90; - lpPointsAlternate[2].y = 80; //{90,80}; - lpPointsAlternate[3].x = 20; - lpPointsAlternate[3].y = 40; //{20,40}; - lpPointsAlternate[4].x = 100; - lpPointsAlternate[4].y = 40; //{100,40}; + //initialize a set of points for alternate. + /*lpPointsAlternate[0].x = 20; + lpPointsAlternate[0].y = 80; //{20,80}; + lpPointsAlternate[1].x = 60; + lpPointsAlternate[1].y = 20; //{60,20}; + lpPointsAlternate[2].x = 90; + lpPointsAlternate[2].y = 80; //{90,80}; + lpPointsAlternate[3].x = 20; + lpPointsAlternate[3].y = 40; //{20,40}; + lpPointsAlternate[4].x = 100; + lpPointsAlternate[4].y = 40; //{100,40}; - //initialize a set of points for winding. - lpPointsWinding[0].x = 130; - lpPointsWinding[0].y = 80; //{130,80}; - lpPointsWinding[1].x = 170; - lpPointsWinding[1].y = 20; //{170,20}; - lpPointsWinding[2].x = 200; - lpPointsWinding[2].y = 80; //{200,80}; - lpPointsWinding[3].x = 130; - lpPointsWinding[3].y = 40; //{130,40}; - lpPointsWinding[4].x = 210; - lpPointsWinding[4].y = 40; //{210,40}; + //initialize a set of points for winding. + lpPointsWinding[0].x = 130; + lpPointsWinding[0].y = 80; //{130,80}; + lpPointsWinding[1].x = 170; + lpPointsWinding[1].y = 20; //{170,20}; + lpPointsWinding[2].x = 200; + lpPointsWinding[2].y = 80; //{200,80}; + lpPointsWinding[3].x = 130; + lpPointsWinding[3].y = 40; //{130,40}; + lpPointsWinding[4].x = 210; + lpPointsWinding[4].y = 40; //{210,40}; +*/ + OldPen = (HPEN)SelectObject(hdc, BluePen); + OldBrush = (HBRUSH)SelectObject(hdc, RedBrush); - OldPen = (HPEN)SelectObject(Desktop, BluePen); - OldBrush = (HBRUSH)SelectObject(Desktop, RedBrush); + Mode = GetPolyFillMode(hdc); - Mode = GetPolyFillMode(Desktop); + SetPolyFillMode(hdc, ALTERNATE); + Polygon(hdc,PointsAlternate,sizeof(PointsAlternate)/sizeof(PointsAlternate[0])); - SetPolyFillMode(Desktop, ALTERNATE); - Polygon(Desktop,lpPointsAlternate,5); + SetPolyFillMode(hdc, WINDING); + Polygon(hdc,PointsWinding,sizeof(PointsWinding)/sizeof(PointsWinding[0])); - SetPolyFillMode(Desktop, WINDING); - Polygon(Desktop,lpPointsWinding,5); - - //cleanup - SetPolyFillMode(Desktop, Mode); - SelectObject(Desktop, OldPen); - SelectObject(Desktop, OldBrush); - DeleteObject(BluePen); - DeleteObject(RedBrush); + Polygon(hdc,Tri1,sizeof(Tri1)/sizeof(Tri1[0])); + Polygon(hdc,Tri2,sizeof(Tri2)/sizeof(Tri2[0])); + Rectangle ( hdc, 3, 15, 7, 20 ); + + //cleanup + SetPolyFillMode(hdc, Mode); + DeleteObject ( SelectObject(hdc, OldPen) ); + DeleteObject ( SelectObject(hdc, OldBrush) ); } -void shaptest( HDC DevCtx ){ - 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); - +void shaptest( HDC hdc ) +{ //Test the Polygon routine. - PolygonTest(DevCtx); + PolygonTest(hdc); } @@ -116,8 +121,8 @@ WinMain(HINSTANCE hInstance, wc.lpfnWndProc = MainWndProc; wc.style = CS_VREDRAW | CS_HREDRAW; wc.hInstance = hInstance; - wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hIcon = (HICON)LoadIcon(NULL, (LPCTSTR)IDI_APPLICATION); + wc.hCursor = (HCURSOR)LoadCursor(NULL, (LPCTSTR)IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH); wc.lpszMenuName = NULL; wc.cbClsExtra = 0; @@ -125,7 +130,7 @@ WinMain(HINSTANCE hInstance, if (RegisterClass(&wc) == 0) { fprintf(stderr, "RegisterClass failed (last error 0x%X)\n", - GetLastError()); + (unsigned int)GetLastError()); return(1); } @@ -143,7 +148,7 @@ WinMain(HINSTANCE hInstance, if (hWnd == NULL) { fprintf(stderr, "CreateWindow failed (last error 0x%X)\n", - GetLastError()); + (unsigned int)GetLastError()); return(1); } @@ -166,27 +171,25 @@ WinMain(HINSTANCE hInstance, LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { - PAINTSTRUCT ps; - HDC hDC; - RECT clr, wir; - char spr[100], sir[100]; + PAINTSTRUCT ps; + HDC hDC; - switch(msg) - { - - case WM_PAINT: - hDC = BeginPaint(hWnd, &ps); - shaptest( hDC ); - EndPaint(hWnd, &ps); - break; + switch(msg) + { + + case WM_PAINT: + hDC = BeginPaint(hWnd, &ps); + shaptest( hDC ); + EndPaint(hWnd, &ps); + break; - case WM_DESTROY: - PostQuitMessage(0); - break; + case WM_DESTROY: + PostQuitMessage(0); + break; - default: - return DefWindowProc(hWnd, msg, wParam, lParam); - } - return 0; + default: + return DefWindowProc(hWnd, msg, wParam, lParam); + } + return 0; } diff --git a/reactos/subsys/win32k/include/paint.h b/reactos/subsys/win32k/include/paint.h index bf17dadc78e..0dc05cd9cf1 100644 --- a/reactos/subsys/win32k/include/paint.h +++ b/reactos/subsys/win32k/include/paint.h @@ -3,6 +3,6 @@ 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_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 */ diff --git a/reactos/subsys/win32k/objects/fillshap.c b/reactos/subsys/win32k/objects/fillshap.c index 1ba13a67835..199cdb0bd74 100644 --- a/reactos/subsys/win32k/objects/fillshap.c +++ b/reactos/subsys/win32k/objects/fillshap.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * 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 #include @@ -83,23 +83,24 @@ W32kPie(HDC hDC, //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. extern BOOL FillPolygon_ALTERNATE(PDC dc, - SURFOBJ *SurfObj, - PBRUSHOBJ BrushObj, - MIX RopMode, - CONST PPOINT Points, - int Count, - RECTL BoundRect); + SURFOBJ *SurfObj, + PBRUSHOBJ BrushObj, + MIX RopMode, + CONST PPOINT Points, + int Count, + RECTL BoundRect); //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. -extern BOOL FillPolygon_WINDING(SURFOBJ *SurfObj, - PBRUSHOBJ BrushObj,MIX RopMode, - CONST PPOINT Points, - int Count, - RECTL BoundRect); +extern BOOL FillPolygon_WINDING(PDC dc, + SURFOBJ *SurfObj, + PBRUSHOBJ BrushObj,MIX RopMode, + CONST PPOINT Points, + int Count, + RECTL BoundRect); #endif //This implementation is blatantly ripped off from W32kRectangle @@ -122,7 +123,7 @@ W32kPolygon(HDC hDC, DPRINT("In W32kPolygon()\n"); - if (NULL == dc || NULL == Points || Count < 2) + if (NULL == dc || NULL == UnsafePoints || Count < 2) { SetLastWin32Error(ERROR_INVALID_PARAMETER); return FALSE; @@ -154,22 +155,22 @@ W32kPolygon(HDC hDC, //ei not yet implemented ASSERT(RectBounds); if (PATH_IsPathOpen(dc->w.path)) - { + { ret = PATH_Polygon(hDC, Points, Count); - } - else + } + else { /* Get the current pen. */ pen = (PENOBJ*) GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC); ASSERT(pen); OutBrushObj = (PBRUSHOBJ) PenToBrushObj(dc, pen); GDIOBJ_UnlockObj(dc->w.hPen, GO_PEN_MAGIC); - + DestRect.left = Points[0].x; DestRect.right = Points[0].x; DestRect.top = Points[0].y; DestRect.bottom = Points[0].y; - + for (CurrentPoint = 1; CurrentPoint < Count; ++CurrentPoint) { DestRect.left = MIN(DestRect.left, Points[CurrentPoint].x); @@ -181,19 +182,20 @@ W32kPolygon(HDC hDC, /* Now fill the polygon with the current brush. */ FillBrushObj = (BRUSHOBJ*) GDIOBJ_LockObj(dc->w.hBrush, GO_BRUSH_MAGIC); /* determine the fill mode to fill the polygon. */ +#if 1 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 */ { ret = FillPolygon_ALTERNATE(dc, SurfObj, FillBrushObj, dc->w.ROPmode, Points, Count, DestRect); } - +#endif // Draw the Polygon Edges with the current pen for (CurrentPoint = 0; CurrentPoint < Count; ++CurrentPoint) - { - POINT To, From, Next; + { + POINT To, From; //, Next; /* Let CurrentPoint be i * if i+1 > Count, Draw a line from Points[i] to Points[0] @@ -209,39 +211,6 @@ W32kPolygon(HDC hDC, 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 ); ret = IntEngLineTo(SurfObj, dc->CombinedClip, @@ -254,6 +223,17 @@ W32kPolygon(HDC hDC, 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); } @@ -297,9 +277,12 @@ W32kRectangle(HDC hDC, RectBounds = GDIOBJ_LockObj(dc->w.hGCClipRgn, GO_REGION_MAGIC); //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); - } else { + } + else + { // Draw the rectangle with the current pen pen = (PENOBJ*) GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC); ASSERT(pen); diff --git a/reactos/subsys/win32k/objects/polyfill.c b/reactos/subsys/win32k/objects/polyfill.c index 966096a20dd..062d2b7afd8 100644 --- a/reactos/subsys/win32k/objects/polyfill.c +++ b/reactos/subsys/win32k/objects/polyfill.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * 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 * PROJECT: ReactOS kernel @@ -47,33 +47,44 @@ */ typedef struct _tagPFILL_EDGE { - /*Basic line information*/ - int FromX; - int FromY; - int ToX; - int ToY; - int dx; - int dy; - int MinX; - int MaxX; - int MinY; - int MaxY; - - /*Active Edge List information*/ - int XIntercept; - int ErrorTerm; - int ErrorTermAdjUp; - int ErrorTermAdjDown; - int XPerY; - int Direction; + /*Basic line information*/ + int FromX; + int FromY; + int ToX; + int ToY; + int dx; + int dy; + int MinX; + int MaxX; + int MinY; + int MaxY; - /* The next edge in the Edge List*/ - struct _tagPFILL_EDGE * pNext; + /*Active Edge List information*/ + 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; -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; if (0 == list) @@ -92,96 +103,101 @@ typedef PPFILL_EDGE PFILL_EDGE_LIST; /* ** Hide memory clean up. */ -static void FASTCALL POLYGONFILL_DestroyEdge(PPFILL_EDGE pEdge) +static +void +FASTCALL +POLYGONFILL_DestroyEdge(PPFILL_EDGE pEdge) { - if (0 != pEdge) - EngFreeMem(pEdge); + if (0 != pEdge) + EngFreeMem(pEdge); } /* ** 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 pNext = 0; + PPFILL_EDGE pThis = 0; + PPFILL_EDGE pNext = 0; - pThis = list; - while (0 != pThis) - { - //DPRINT("Destroying Edge\n"); - pNext = pThis->pNext; - POLYGONFILL_DestroyEdge(pThis); - pThis = pNext; - } - + pThis = list; + while (0 != pThis) + { + //DPRINT("Destroying Edge\n"); + pNext = pThis->pNext; + POLYGONFILL_DestroyEdge(pThis); + pThis = pNext; + } } /* ** 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) - { - //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 (0 == rc) + return NULL; - if (rc->MinY == To.y) - rc->XIntercept = To.x; - else - rc->XIntercept = From.x; + //DPRINT ("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; + } + 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->Direction = (rc->dx < 0)?(-1):(1); - - if (rc->dx >= 0) /*edge goes l to r*/ - { - rc->ErrorTerm = 0; - } - else/*edge goes r to l*/ - { - rc->ErrorTerm = -rc->dy +1; - } + rc->dx = rc->ToX - rc->FromX; + rc->dy = rc->ToY - rc->FromY; + absdx = abs(rc->dx); + absdy = abs(rc->dy); + 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); - /*Now which part of the slope is greater?*/ - if (rc->dy == 0) - { - rc->XPerY = 0; - rc->ErrorTermAdjUp = 0; - } - else if (rc->dy >= rc->dx) - { - rc->XPerY = 0; - rc->ErrorTermAdjUp = rc->dx; - } - else - { - rc->XPerY = rc->dx / rc->dy; - rc->ErrorTermAdjUp = rc->dx % rc->dy; - } - - rc->pNext = 0; - } - return rc; + if (rc->MinY == To.y) + rc->XIntercept = To.x; + else + rc->XIntercept = From.x; + + rc->ErrorMax = absdy; + rc->ErrorInc = absdx; + + 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 err=%i max=%i\n", + From.x, From.y, To.x, To.y, rc->dx, rc->dy, rc->Direction, rc->Error, rc->ErrorMax ); + + return rc; } /* ** My Edge comparison routine. ** 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 ** 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 ** 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"); - if (Edge1->MinY == Edge2->MinY) + //DPRINT("In PFILL_EDGE_Compare()\n"); + 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 (Edge1->MinX == Edge2->MinX) - { - if (0 == Edge2->dx || 0 == Edge1->dx) - { - return Edge1->dx - Edge2->dx; - } - else - { - return (Edge1->dy/Edge1->dx) - (Edge2->dy/Edge2->dx); - } - } - else - { - return Edge1->MinX - Edge2->MinX; - } + if (0 == Edge2->dx || 0 == Edge1->dx) + { + return Edge1->dx - Edge2->dx; + } + else + { + return (Edge1->dy/Edge1->dx) - (Edge2->dy/Edge2->dx); + } } - //DPRINT("In PFILL_EDGE_Compare() returning: %d\n",Edge1->MinY - Edge2->MinY); - return Edge1->MinY - Edge2->MinY; - + else + { + 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. */ -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; - if (0 != list && 0 != NewEdge) + PPFILL_EDGE pThis; + 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; - //DPRINT("In POLYGONFILL_ListInsert()\n"); - /* - ** 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); + 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); + } } /* ** 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 SeqNum = 0; - PPFILL_EDGE rc = 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; + int CurPt = 0; + int SeqNum = 0; + PPFILL_EDGE rc = 0; + PPFILL_EDGE NextEdge = 0; - for (CurPt = 1; CurPt < Count; ++CurPt,++SeqNum) - { - if (CurPt == Count - 1) - { - NextEdge = POLYGONFILL_MakeEdge(Points[CurPt],Points[0]); - } - else - { - NextEdge = POLYGONFILL_MakeEdge(Points[CurPt],Points[CurPt + 1]); - } - if (0 != NextEdge) - { - POLYGONFILL_ListInsert(&rc, NextEdge); - } - else - { - DPRINT("Out Of MEMORY!! NextEdge = 0\n"); - } - } - } - return rc; + if ( 0 == Points || 2 > Count ) + return rc; + + //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 (CurPt == Count - 1 ) + { + NextEdge = POLYGONFILL_MakeEdge(Points[CurPt],Points[0]); + } + else + { + NextEdge = POLYGONFILL_MakeEdge(Points[CurPt],Points[CurPt + 1]); + } + if (0 != NextEdge) + { + POLYGONFILL_ListInsert(&rc, NextEdge); + } + 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. **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) { - - int Coord = 0; - float XCoord = 0; - if (0 == pEdge->dy) return; + if ( 0 == pEdge->dy ) + return; - XCoord = (Scanline*pEdge->dx - pEdge->FromY*pEdge->dx)/pEdge->dy + pEdge->FromX; - Coord = XCoord + 0.5; - - //DPRINT("Line (%d, %d) to (%d, %d) intersects scanline %d at %d\n", - // pEdge->FromX, pEdge->FromY, pEdge->ToX, pEdge->ToY, Scanline, Coord); - pEdge->XIntercept = Coord; - - - /*pEdge->XIntercept += pEdge->XPerY; - - if ((pEdge->ErrorTerm += pEdge->ErrorTermAdjUp) > 0) + if ( pEdge->ErrorMax ) + { + pEdge->Error += pEdge->ErrorInc; + if ( pEdge->Error >= pEdge->ErrorMax ) { - pEdge->XIntercept += pEdge->Direction; - pEdge->ErrorTerm -= pEdge->ErrorTermAdjDown; - }*/ + int steps = pEdge->Error / pEdge->ErrorMax; + 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. */ -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; - PPFILL_EDGE pThis = 0; - PPFILL_EDGE pPrev = 0; - pThis = *list; - while(0 != pThis && !Done) + BOOL Done = FALSE; + PPFILL_EDGE pThis = 0; + PPFILL_EDGE pPrev = 0; + pThis = *list; + while(0 != pThis && !Done) + { + /*pEdge goes before pThis*/ + if (pThis->XIntercept > pEdge->XIntercept) { - /*pEdge goes before pThis*/ - if (pThis->XIntercept > pEdge->XIntercept) - { - if (*list == pThis) - { - *list = pEdge; - } - else - { - pPrev->pNext = pEdge; - } - pEdge->pNext = pThis; - Done = TRUE; - } - pPrev = pThis; - pThis = pThis->pNext; + if (*list == pThis) + { + *list = pEdge; + } + else + { + pPrev->pNext = pEdge; + } + pEdge->pNext = pThis; + Done = TRUE; } + pPrev = pThis; + pThis = pThis->pNext; + } } /* ** This routine reorders the Active Edge collection (list) after all ** 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 pPrev = 0; - PPFILL_EDGE pTarg = 0; - pThis = *AEC; - - while (0 != pThis) - { - /*We are at the end of the list*/ - if (0 == pThis->pNext) - { - return; - } + PPFILL_EDGE pThis = 0; + PPFILL_EDGE pPrev = 0; + PPFILL_EDGE pTarg = 0; + pThis = *AEC; - /*If the next item is out of order, pull it from the list and - re-insert it, and don't advance pThis.*/ - if (pThis->XIntercept > pThis->pNext->XIntercept) - { - pTarg = pThis->pNext; - pThis->pNext = pTarg->pNext; - pTarg->pNext = 0; - POLYGONFILL_AECInsertInOrder(AEC, pTarg); - } - else/*In order, advance pThis*/ - { - pPrev = pThis; - pThis = pThis->pNext; - } + 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 + re-insert it, and don't advance pThis.*/ + if (pThis->XIntercept > pThis->pNext->XIntercept) + { + pTarg = pThis->pNext; + pThis->pNext = pTarg->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. */ -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 pAECLast = 0; - PPFILL_EDGE pPrev = 0; - DPRINT("In POLYGONFILL_UpdateActiveEdges() Scanline: %d\n", Scanline); - /*First scan through GEC and look for any edges that have become active*/ + PPFILL_EDGE pThis = 0; + PPFILL_EDGE pAECLast = 0; + PPFILL_EDGE pPrev = 0; + DPRINT("In POLYGONFILL_UpdateActiveEdges() Scanline: %d\n", Scanline); + /*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; - 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"); - /*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; + //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); } - /*Now remove any edges in the AEC that are no longer active and Update the XIntercept in the AEC*/ - pThis = *AEC; - while (0 != pThis) + else/*Otherwise, update the scanline*/ { - /*First check to see if this item is deleted*/ - if (pThis->MaxY <= Scanline) - { - //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; - } + POLYGONFILL_UpdateScanline(pThis, Scanline); + pPrev = pThis; } - /*Last re Xintercept order the AEC*/ - POLYGONFILL_AECReorder(AEC); - + /*List Upkeep*/ + 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 ** 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; RECTL BoundRect; int XInterceptOdd,XInterceptEven,ret; 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; - DPRINT("Fill Line (%d, %d) to (%d, %d)\n",XInterceptOdd - 1, ScanLine, XInterceptEven - 1, ScanLine); - ret = IntEngLineTo(SurfObj, - dc->CombinedClip, - BrushObj, - XInterceptOdd - 1, - ScanLine, - XInterceptEven - 1, - ScanLine, - &BoundRect, /* Bounding rectangle */ - RopMode); /* MIX */ - OnOdd = TRUE; - } - pThis = pThis->pNext; + while (NULL != pThis) + { + if (OnOdd) + { + XInterceptOdd = pThis->XIntercept; + OnOdd = FALSE; } + 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 @@ -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 //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. -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 ActiveEdges = 0; int ScanLine; DPRINT("FillPolygon_ALTERNATE\n"); - + /* Create Edge List. */ list = POLYGONFILL_MakeEdgeList(Points, Count); /* DEBUG_PRINT_EDGELIST(list); */ if (NULL == list) - { - return FALSE; - } + 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_FillScanLine(dc, ScanLine, ActiveEdges, SurfObj, BrushObj, RopMode); - } - + for ( ScanLine = BoundRect.top + 1; ScanLine < BoundRect.bottom; ++ScanLine ) + { + POLYGONFILL_UpdateActiveEdges(ScanLine, &list, &ActiveEdges); + /* DEBUG_PRINT_EDGELIST(ActiveEdges); */ + POLYGONFILL_FillScanLineAlternate(dc, ScanLine, ActiveEdges, SurfObj, BrushObj, RopMode); + } + /* Free Edge List. If any are left. */ 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. //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 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 */