mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
Polygon now works flawlessly ( with possible exception to the issue mentioned on the list earlier this evening ). Scrollbar arrows are now perfect.
svn path=/trunk/; revision=5595
This commit is contained in:
parent
58d4ce9842
commit
321a71f1dd
4 changed files with 439 additions and 551 deletions
|
@ -19,24 +19,50 @@
|
||||||
#define FASTCALL
|
#define FASTCALL
|
||||||
#define STDCALL
|
#define STDCALL
|
||||||
#define INT int
|
#define INT int
|
||||||
|
#define CLIPOBJ int
|
||||||
|
#define SURFOBJ int
|
||||||
|
#define PBRUSHOBJ int
|
||||||
|
#define MIX char
|
||||||
#define BOOL bool
|
#define BOOL bool
|
||||||
#define TRUE true
|
#define TRUE true
|
||||||
#define FALSE false
|
#define FALSE false
|
||||||
#define CONST const
|
#define CONST const
|
||||||
#define MmCopyFromCaller memmove
|
#define MmCopyFromCaller memmove
|
||||||
|
#define ALTERNATE 0
|
||||||
|
#define WINDING 1
|
||||||
|
|
||||||
#define ASSERT assert
|
#define ASSERT assert
|
||||||
|
|
||||||
#define EngFreeMem free
|
typedef struct W
|
||||||
|
{
|
||||||
|
int polyFillMode;
|
||||||
|
} W;
|
||||||
|
|
||||||
#define FILL_EDGE_ALLOC_TAG 0x45465044
|
typedef struct DC
|
||||||
|
{
|
||||||
|
CLIPOBJ CombinedClip;
|
||||||
|
W w;
|
||||||
|
} DC, *PDC;
|
||||||
|
|
||||||
|
typedef struct tagPOINT
|
||||||
|
{
|
||||||
|
long x, y;
|
||||||
|
} POINT, *PPOINT, *LPPOINT;
|
||||||
|
|
||||||
|
typedef struct RECTL
|
||||||
|
{
|
||||||
|
long left, top, right, bottom;
|
||||||
|
} RECTL, *PRECTL;
|
||||||
|
|
||||||
|
#define EngFreeMem free
|
||||||
|
|
||||||
#define FL_ZERO_MEMORY 1
|
#define FL_ZERO_MEMORY 1
|
||||||
|
|
||||||
#define DPRINT1 printf("%i:",__LINE__);printf
|
#define DPRINT1 printf("%i:",__LINE__);printf
|
||||||
|
inline void DPRINT(...){}
|
||||||
|
|
||||||
#define SCREENX 16
|
#define SCREENX 25
|
||||||
#define SCREENY 16
|
#define SCREENY 25
|
||||||
char screen[SCREENY][SCREENX];
|
char screen[SCREENY][SCREENX];
|
||||||
|
|
||||||
#define EDGE_CHAR '*'
|
#define EDGE_CHAR '*'
|
||||||
|
@ -79,7 +105,13 @@ void putpixel ( int x, int y, char c )
|
||||||
screen[y][x] = '#';
|
screen[y][x] = '#';
|
||||||
}
|
}
|
||||||
|
|
||||||
void Line ( int x1, int y1, int x2, int y2, char c )
|
void IntEngLineTo (
|
||||||
|
SURFOBJ*,
|
||||||
|
CLIPOBJ,
|
||||||
|
PBRUSHOBJ,
|
||||||
|
int x1, int y1, int x2, int y2,
|
||||||
|
RECTL*,
|
||||||
|
MIX mix )
|
||||||
{
|
{
|
||||||
int dx = x2 - x1;
|
int dx = x2 - x1;
|
||||||
int dy = y2 - y1;
|
int dy = y2 - y1;
|
||||||
|
@ -93,7 +125,7 @@ void Line ( int x1, int y1, int x2, int y2, char c )
|
||||||
{
|
{
|
||||||
while ( x1 != x2 )
|
while ( x1 != x2 )
|
||||||
{
|
{
|
||||||
putpixel ( x1, y1, c );
|
putpixel ( x1, y1, mix );
|
||||||
x1 += xinc;
|
x1 += xinc;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -102,14 +134,14 @@ void Line ( int x1, int y1, int x2, int y2, char c )
|
||||||
{
|
{
|
||||||
while ( y1 != y2 )
|
while ( y1 != y2 )
|
||||||
{
|
{
|
||||||
putpixel ( x1, y1, c );
|
putpixel ( x1, y1, mix );
|
||||||
y1 += yinc;
|
y1 += yinc;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for ( int i = 0; i < EMax; i++ )
|
for ( int i = 0; i < EMax; i++ )
|
||||||
{
|
{
|
||||||
putpixel ( x1, y1, c );
|
putpixel ( x1, y1, mix );
|
||||||
if ( absdy > absdx )
|
if ( absdy > absdx )
|
||||||
{
|
{
|
||||||
y1 += yinc;
|
y1 += yinc;
|
||||||
|
@ -133,15 +165,7 @@ void Line ( int x1, int y1, int x2, int y2, char c )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct tagPOINT
|
#define FILL_EDGE_ALLOC_TAG 0x45465044
|
||||||
{
|
|
||||||
long x, y;
|
|
||||||
} POINT, *PPOINT, *LPPOINT;
|
|
||||||
|
|
||||||
typedef struct tagRECTL
|
|
||||||
{
|
|
||||||
long left, top, right, bottom;
|
|
||||||
} RECTL, *PRECTL;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This struct is used for book keeping during polygon filling routines.
|
** This struct is used for book keeping during polygon filling routines.
|
||||||
|
@ -288,7 +312,7 @@ POLYGONFILL_MakeEdge(POINT From, POINT To)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT1("MakeEdge (%i,%i)->(%i,%i) d=(%i,%i) dir=(%i,%i) err=%i max=%i\n",
|
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 );
|
From.x, From.y, To.x, To.y, rc->dx, rc->dy, rc->XDirection, rc->YDirection, rc->Error, rc->ErrorMax );
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -478,7 +502,7 @@ POLYGONFILL_UpdateScanline(FILL_EDGE* pEdge, int Scanline)
|
||||||
pEdge->XIntercept[1] = pEdge->x;
|
pEdge->XIntercept[1] = pEdge->x;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT1("Line (%d, %d) to (%d, %d) intersects scanline %d at (%d,%d)\n",
|
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] );
|
pEdge->FromX, pEdge->FromY, pEdge->ToX, pEdge->ToY, Scanline, pEdge->XIntercept[0], pEdge->XIntercept[1] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,7 +537,13 @@ POLYGONFILL_BuildActiveList ( int Scanline, FILL_EDGE_LIST* list, FILL_EDGE** Ac
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
STDCALL
|
STDCALL
|
||||||
POLYGONFILL_FillScanLineAlternate ( int ScanLine, FILL_EDGE* ActiveHead )
|
POLYGONFILL_FillScanLineAlternate(
|
||||||
|
PDC dc,
|
||||||
|
int ScanLine,
|
||||||
|
FILL_EDGE* ActiveHead,
|
||||||
|
SURFOBJ *SurfObj,
|
||||||
|
PBRUSHOBJ BrushObj,
|
||||||
|
MIX RopMode )
|
||||||
{
|
{
|
||||||
FILL_EDGE *pLeft, *pRight;
|
FILL_EDGE *pLeft, *pRight;
|
||||||
|
|
||||||
|
@ -536,9 +566,8 @@ POLYGONFILL_FillScanLineAlternate ( int ScanLine, FILL_EDGE* ActiveHead )
|
||||||
BoundRect.left = x1;
|
BoundRect.left = x1;
|
||||||
BoundRect.right = x2;
|
BoundRect.right = x2;
|
||||||
|
|
||||||
DPRINT1("Fill Line (%d, %d) to (%d, %d)\n",x1, ScanLine, x2, ScanLine);
|
DPRINT("Fill Line (%d, %d) to (%d, %d)\n",x1, ScanLine, x2, ScanLine);
|
||||||
Line ( x1, ScanLine, x2, ScanLine, FILL_CHAR );
|
IntEngLineTo( SurfObj,
|
||||||
/*ret = IntEngLineTo( SurfObj,
|
|
||||||
dc->CombinedClip,
|
dc->CombinedClip,
|
||||||
BrushObj,
|
BrushObj,
|
||||||
x1,
|
x1,
|
||||||
|
@ -546,7 +575,7 @@ POLYGONFILL_FillScanLineAlternate ( int ScanLine, FILL_EDGE* ActiveHead )
|
||||||
x2,
|
x2,
|
||||||
ScanLine,
|
ScanLine,
|
||||||
&BoundRect, // Bounding rectangle
|
&BoundRect, // Bounding rectangle
|
||||||
RopMode);*/ // MIX
|
RopMode); // MIX
|
||||||
}
|
}
|
||||||
pLeft = pRight->pNext;
|
pLeft = pRight->pNext;
|
||||||
pRight = pLeft ? pLeft->pNext : NULL;
|
pRight = pLeft ? pLeft->pNext : NULL;
|
||||||
|
@ -556,7 +585,13 @@ POLYGONFILL_FillScanLineAlternate ( int ScanLine, FILL_EDGE* ActiveHead )
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
STDCALL
|
STDCALL
|
||||||
POLYGONFILL_FillScanLineWinding ( int ScanLine, FILL_EDGE* ActiveHead )
|
POLYGONFILL_FillScanLineWinding(
|
||||||
|
PDC dc,
|
||||||
|
int ScanLine,
|
||||||
|
FILL_EDGE* ActiveHead,
|
||||||
|
SURFOBJ *SurfObj,
|
||||||
|
PBRUSHOBJ BrushObj,
|
||||||
|
MIX RopMode )
|
||||||
{
|
{
|
||||||
FILL_EDGE *pLeft, *pRight;
|
FILL_EDGE *pLeft, *pRight;
|
||||||
int winding = 0;
|
int winding = 0;
|
||||||
|
@ -581,9 +616,8 @@ POLYGONFILL_FillScanLineWinding ( int ScanLine, FILL_EDGE* ActiveHead )
|
||||||
BoundRect.left = x1;
|
BoundRect.left = x1;
|
||||||
BoundRect.right = x2;
|
BoundRect.right = x2;
|
||||||
|
|
||||||
DPRINT1("Fill Line (%d, %d) to (%d, %d)\n",x1, ScanLine, x2, ScanLine);
|
DPRINT("Fill Line (%d, %d) to (%d, %d)\n",x1, ScanLine, x2, ScanLine);
|
||||||
Line ( x1, ScanLine, x2, ScanLine, FILL_CHAR );
|
IntEngLineTo( SurfObj,
|
||||||
/*ret = IntEngLineTo( SurfObj,
|
|
||||||
dc->CombinedClip,
|
dc->CombinedClip,
|
||||||
BrushObj,
|
BrushObj,
|
||||||
x1,
|
x1,
|
||||||
|
@ -591,64 +625,49 @@ POLYGONFILL_FillScanLineWinding ( int ScanLine, FILL_EDGE* ActiveHead )
|
||||||
x2,
|
x2,
|
||||||
ScanLine,
|
ScanLine,
|
||||||
&BoundRect, // Bounding rectangle
|
&BoundRect, // Bounding rectangle
|
||||||
RopMode);*/ // MIX
|
RopMode); // MIX
|
||||||
}
|
}
|
||||||
pLeft = pRight;
|
pLeft = pRight;
|
||||||
pRight = pLeft->pNext;
|
pRight = pLeft->pNext;
|
||||||
winding += pLeft->XDirection;
|
winding += pLeft->YDirection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//ALTERNATE Selects alternate mode (fills the area between odd-numbered and even-numbered
|
|
||||||
//polygon sides on each scan line).
|
|
||||||
//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(CONST PPOINT Points, int Count, RECTL BoundRect)
|
|
||||||
{
|
|
||||||
FILL_EDGE_LIST *list = 0;
|
|
||||||
FILL_EDGE *ActiveHead = 0;
|
|
||||||
int ScanLine;
|
|
||||||
|
|
||||||
DPRINT1("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_BuildActiveList(ScanLine, list, &ActiveHead);
|
|
||||||
//DEBUG_PRINT_ACTIVE_EDGELIST(ActiveHead);
|
|
||||||
POLYGONFILL_FillScanLineAlternate(ScanLine, ActiveHead);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free Edge List. If any are left. */
|
|
||||||
POLYGONFILL_DestroyEdgeList(list);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
//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.
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
STDCALL
|
STDCALL
|
||||||
FillPolygon_WINDING(CONST PPOINT Points, int Count, RECTL BoundRect)
|
FillPolygon(
|
||||||
|
PDC dc,
|
||||||
|
SURFOBJ *SurfObj,
|
||||||
|
PBRUSHOBJ BrushObj,
|
||||||
|
MIX RopMode,
|
||||||
|
CONST PPOINT Points,
|
||||||
|
int Count,
|
||||||
|
RECTL BoundRect )
|
||||||
{
|
{
|
||||||
FILL_EDGE_LIST *list = 0;
|
FILL_EDGE_LIST *list = 0;
|
||||||
FILL_EDGE *ActiveHead = 0;
|
FILL_EDGE *ActiveHead = 0;
|
||||||
int ScanLine;
|
int ScanLine;
|
||||||
|
|
||||||
DPRINT1("FillPolygon_WINDING\n");
|
void
|
||||||
|
STDCALL
|
||||||
|
(*FillScanLine)(
|
||||||
|
PDC dc,
|
||||||
|
int ScanLine,
|
||||||
|
FILL_EDGE* ActiveHead,
|
||||||
|
SURFOBJ *SurfObj,
|
||||||
|
PBRUSHOBJ BrushObj,
|
||||||
|
MIX RopMode );
|
||||||
|
|
||||||
|
DPRINT("FillPolygon\n");
|
||||||
|
|
||||||
/* Create Edge List. */
|
/* Create Edge List. */
|
||||||
list = POLYGONFILL_MakeEdgeList(Points, Count);
|
list = POLYGONFILL_MakeEdgeList(Points, Count);
|
||||||
|
@ -656,6 +675,11 @@ FillPolygon_WINDING(CONST PPOINT Points, int Count, RECTL BoundRect)
|
||||||
if (NULL == list)
|
if (NULL == list)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
if ( WINDING == dc->w.polyFillMode )
|
||||||
|
FillScanLine = POLYGONFILL_FillScanLineWinding;
|
||||||
|
else /* default */
|
||||||
|
FillScanLine = POLYGONFILL_FillScanLineAlternate;
|
||||||
|
|
||||||
/* 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
|
||||||
*/
|
*/
|
||||||
|
@ -663,7 +687,7 @@ FillPolygon_WINDING(CONST PPOINT Points, int Count, RECTL BoundRect)
|
||||||
{
|
{
|
||||||
POLYGONFILL_BuildActiveList(ScanLine, list, &ActiveHead);
|
POLYGONFILL_BuildActiveList(ScanLine, list, &ActiveHead);
|
||||||
//DEBUG_PRINT_ACTIVE_EDGELIST(ActiveHead);
|
//DEBUG_PRINT_ACTIVE_EDGELIST(ActiveHead);
|
||||||
POLYGONFILL_FillScanLineWinding(ScanLine, ActiveHead);
|
FillScanLine ( dc, ScanLine, ActiveHead, SurfObj, BrushObj, RopMode );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free Edge List. If any are left. */
|
/* Free Edge List. If any are left. */
|
||||||
|
@ -674,35 +698,22 @@ FillPolygon_WINDING(CONST PPOINT Points, int Count, RECTL BoundRect)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ReactOS W32 Subsystem
|
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
*/
|
|
||||||
/* $Id: polytest.cpp,v 1.1 2003/08/16 01:34:29 royce Exp $ */
|
|
||||||
|
|
||||||
|
|
||||||
//This implementation is blatantly ripped off from W32kRectangle
|
// this is highly hacked from W32kPolygon...
|
||||||
BOOL
|
BOOL
|
||||||
Polygon ( CONST PPOINT UnsafePoints, int Count )
|
Polygon ( CONST PPOINT UnsafePoints, int Count, int polyFillMode )
|
||||||
{
|
{
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
RECTL DestRect;
|
RECTL DestRect;
|
||||||
int CurrentPoint;
|
int CurrentPoint;
|
||||||
PPOINT Points;
|
PPOINT Points;
|
||||||
|
SURFOBJ* SurfObj = 0;
|
||||||
|
DC dc;
|
||||||
|
PBRUSHOBJ OutBrushObj = 0;
|
||||||
|
|
||||||
|
dc.CombinedClip = 0;
|
||||||
|
dc.w.polyFillMode = polyFillMode;
|
||||||
|
|
||||||
DPRINT1("In W32kPolygon()\n");
|
DPRINT1("In W32kPolygon()\n");
|
||||||
|
|
||||||
|
@ -759,20 +770,18 @@ Polygon ( CONST PPOINT UnsafePoints, int Count )
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT1("Polygon Making line from (%d,%d) to (%d,%d)\n", From.x, From.y, To.x, To.y );
|
DPRINT1("Polygon Making line from (%d,%d) to (%d,%d)\n", From.x, From.y, To.x, To.y );
|
||||||
Line ( From.x, From.y, To.x, To.y, EDGE_CHAR );
|
IntEngLineTo(SurfObj,
|
||||||
/*ret = IntEngLineTo(SurfObj,
|
dc.CombinedClip,
|
||||||
dc->CombinedClip,
|
OutBrushObj,
|
||||||
OutBrushObj,
|
From.x,
|
||||||
From.x,
|
From.y,
|
||||||
From.y,
|
To.x,
|
||||||
To.x,
|
To.y,
|
||||||
To.y,
|
&DestRect,
|
||||||
&DestRect,
|
EDGE_CHAR); /* MIX */
|
||||||
dc->w.ROPmode);*/ /* MIX */
|
|
||||||
|
|
||||||
}
|
}
|
||||||
/* determine the fill mode to fill the polygon. */
|
/* determine the fill mode to fill the polygon. */
|
||||||
ret = FillPolygon_ALTERNATE(Points, Count, DestRect);
|
ret = FillPolygon(&dc, SurfObj, OutBrushObj, FILL_CHAR, Points, Count, DestRect );
|
||||||
free(Points);
|
free(Points);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -789,14 +798,19 @@ void main()
|
||||||
{ 12, 4 },
|
{ 12, 4 },
|
||||||
{ 4, 8 },
|
{ 4, 8 },
|
||||||
#else
|
#else
|
||||||
{ 2, 8 },
|
{ 4, 16 },
|
||||||
{ 6, 2 },
|
{ 12, 4 },
|
||||||
{ 9, 8 },
|
{ 18, 16 },
|
||||||
{ 2, 4 },
|
{ 4, 8 },
|
||||||
{ 10, 4 }
|
{ 20, 8 }
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
Polygon ( pts,sizeof(pts)/sizeof(pts[0]) );
|
const int pts_count = sizeof(pts)/sizeof(pts[0]);
|
||||||
|
|
||||||
|
// use ALTERNATE or WINDING for 3rd param
|
||||||
|
Polygon ( pts, pts_count, ALTERNATE );
|
||||||
|
|
||||||
|
// print out our "screen"
|
||||||
for ( int y = 0; y < SCREENY; y++ )
|
for ( int y = 0; y < SCREENY; y++ )
|
||||||
{
|
{
|
||||||
for ( int x = 0; x < SCREENX; x++ )
|
for ( int x = 0; x < SCREENX; x++ )
|
||||||
|
@ -808,4 +822,4 @@ void main()
|
||||||
DPRINT1("Done!\n");
|
DPRINT1("Done!\n");
|
||||||
(void)getch();
|
(void)getch();
|
||||||
}
|
}
|
||||||
|
/* EOF */
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
#define __WIN32K_PAINT_H
|
#define __WIN32K_PAINT_H
|
||||||
|
|
||||||
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 ( PDC dc, 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 */
|
||||||
|
|
|
@ -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.22 2003/08/15 18:51:32 royce Exp $ */
|
/* $Id: fillshap.c,v 1.23 2003/08/16 04:47:41 royce Exp $ */
|
||||||
|
|
||||||
#undef WIN32_LEAN_AND_MEAN
|
#undef WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
@ -77,12 +77,16 @@ W32kPie(HDC hDC,
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
||||||
//ALTERNATE Selects alternate mode (fills the area between odd-numbered and even-numbered
|
|
||||||
//polygon sides on each scan line).
|
|
||||||
//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.
|
||||||
extern BOOL FillPolygon_ALTERNATE(PDC dc,
|
|
||||||
|
//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(PDC dc,
|
||||||
SURFOBJ *SurfObj,
|
SURFOBJ *SurfObj,
|
||||||
PBRUSHOBJ BrushObj,
|
PBRUSHOBJ BrushObj,
|
||||||
MIX RopMode,
|
MIX RopMode,
|
||||||
|
@ -90,17 +94,6 @@ extern BOOL FillPolygon_ALTERNATE(PDC dc,
|
||||||
int Count,
|
int Count,
|
||||||
RECTL BoundRect);
|
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(PDC dc,
|
|
||||||
SURFOBJ *SurfObj,
|
|
||||||
PBRUSHOBJ BrushObj,MIX RopMode,
|
|
||||||
CONST PPOINT Points,
|
|
||||||
int Count,
|
|
||||||
RECTL BoundRect);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//This implementation is blatantly ripped off from W32kRectangle
|
//This implementation is blatantly ripped off from W32kRectangle
|
||||||
|
@ -181,16 +174,9 @@ 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. */
|
|
||||||
#if 1
|
#if 1
|
||||||
if (WINDING == dc->w.polyFillMode)
|
ret = FillPolygon ( dc, 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
|
#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)
|
||||||
|
@ -224,15 +210,7 @@ W32kPolygon(HDC hDC,
|
||||||
|
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
/* determine the fill mode to fill the polygon. */
|
ret = FillPolygon ( dc, SurfObj, FillBrushObj, dc->w.ROPmode, Points, Count, DestRect);
|
||||||
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
|
#endif
|
||||||
GDIOBJ_UnlockObj(dc->w.hBrush, GO_BRUSH_MAGIC);
|
GDIOBJ_UnlockObj(dc->w.hBrush, GO_BRUSH_MAGIC);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.7 2003/08/15 18:51:32 royce Exp $
|
/* $Id: polyfill.c,v 1.8 2003/08/16 04:47:41 royce Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -40,12 +40,12 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <win32k/debug1.h>
|
#include <win32k/debug1.h>
|
||||||
|
|
||||||
#define PFILL_EDGE_ALLOC_TAG 0x45465044
|
#define FILL_EDGE_ALLOC_TAG 0x45465044
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This struct is used for book keeping during polygon filling routines.
|
** This struct is used for book keeping during polygon filling routines.
|
||||||
*/
|
*/
|
||||||
typedef struct _tagPFILL_EDGE
|
typedef struct _tagFILL_EDGE
|
||||||
{
|
{
|
||||||
/*Basic line information*/
|
/*Basic line information*/
|
||||||
int FromX;
|
int FromX;
|
||||||
|
@ -54,51 +54,48 @@ typedef struct _tagPFILL_EDGE
|
||||||
int ToY;
|
int ToY;
|
||||||
int dx;
|
int dx;
|
||||||
int dy;
|
int dy;
|
||||||
int MinX;
|
int absdx, absdy;
|
||||||
int MaxX;
|
int x, y;
|
||||||
int MinY;
|
int xmajor;
|
||||||
int MaxY;
|
|
||||||
|
|
||||||
/*Active Edge List information*/
|
/*Active Edge List information*/
|
||||||
int XIntercept;
|
int XIntercept[2];
|
||||||
int Error;
|
int Error;
|
||||||
int ErrorInc;
|
|
||||||
int ErrorMax;
|
int ErrorMax;
|
||||||
int XPerY;
|
int XDirection, YDirection;
|
||||||
int XDirection;
|
|
||||||
int YDirection; // used for Winding
|
|
||||||
|
|
||||||
/* The next edge in the Edge List*/
|
/* The next edge in the active Edge List*/
|
||||||
struct _tagPFILL_EDGE * pNext;
|
struct _tagFILL_EDGE * pNext;
|
||||||
} PFILL_EDGE, *PPFILL_EDGE;
|
} FILL_EDGE;
|
||||||
|
|
||||||
typedef PPFILL_EDGE PFILL_EDGE_LIST;
|
typedef struct _FILL_EDGE_LIST
|
||||||
|
{
|
||||||
|
int Count;
|
||||||
|
FILL_EDGE** Edges;
|
||||||
|
} FILL_EDGE_LIST;
|
||||||
|
|
||||||
|
#if 0
|
||||||
static
|
static
|
||||||
inline
|
|
||||||
int
|
|
||||||
abs ( int a )
|
|
||||||
{
|
|
||||||
return a < 0 ? -a : a;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*static
|
|
||||||
void
|
void
|
||||||
DEBUG_PRINT_EDGELIST(PFILL_EDGE_LIST list)
|
DEBUG_PRINT_ACTIVE_EDGELIST ( FILL_EDGE* list )
|
||||||
{
|
{
|
||||||
PPFILL_EDGE pThis = list;
|
FILL_EDGE* pThis = list;
|
||||||
if (0 == list)
|
if (0 == list)
|
||||||
{
|
{
|
||||||
DPRINT("List is NULL\n");
|
DPRINT1("List is NULL\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while(0 != pThis)
|
while(0 != pThis)
|
||||||
{
|
{
|
||||||
DPRINT("EDGE: (%d, %d) to (%d, %d)\n", pThis->FromX, pThis->FromY, pThis->ToX, pThis->ToY);
|
//DPRINT1("EDGE: (%d, %d) to (%d, %d)\n", pThis->FromX, pThis->FromY, pThis->ToX, pThis->ToY);
|
||||||
pThis = pThis->pNext;
|
DPRINT1("EDGE: [%d,%d]\n", pThis->XIntercept[0], pThis->XIntercept[1] );
|
||||||
}
|
pThis = pThis->pNext;
|
||||||
}*/
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define DEBUG_PRINT_ACTIVE_EDGELIST(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Hide memory clean up.
|
** Hide memory clean up.
|
||||||
|
@ -106,30 +103,21 @@ DEBUG_PRINT_EDGELIST(PFILL_EDGE_LIST list)
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
FASTCALL
|
FASTCALL
|
||||||
POLYGONFILL_DestroyEdge(PPFILL_EDGE pEdge)
|
POLYGONFILL_DestroyEdgeList(FILL_EDGE_LIST* list)
|
||||||
{
|
{
|
||||||
if (0 != pEdge)
|
int i;
|
||||||
EngFreeMem(pEdge);
|
if ( list )
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Clean up a list.
|
|
||||||
*/
|
|
||||||
static
|
|
||||||
void
|
|
||||||
FASTCALL
|
|
||||||
POLYGONFILL_DestroyEdgeList(PFILL_EDGE_LIST list)
|
|
||||||
{
|
|
||||||
PPFILL_EDGE pThis = 0;
|
|
||||||
PPFILL_EDGE pNext = 0;
|
|
||||||
|
|
||||||
pThis = list;
|
|
||||||
while (0 != pThis)
|
|
||||||
{
|
{
|
||||||
//DPRINT("Destroying Edge\n");
|
if ( list->Edges )
|
||||||
pNext = pThis->pNext;
|
{
|
||||||
POLYGONFILL_DestroyEdge(pThis);
|
for ( i = 0; i < list->Count; i++ )
|
||||||
pThis = pNext;
|
{
|
||||||
|
if ( list->Edges[i] )
|
||||||
|
EngFreeMem ( list->Edges[i] );
|
||||||
|
}
|
||||||
|
EngFreeMem ( list->Edges );
|
||||||
|
}
|
||||||
|
EngFreeMem ( list );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,17 +125,16 @@ POLYGONFILL_DestroyEdgeList(PFILL_EDGE_LIST list)
|
||||||
** 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
|
static
|
||||||
PPFILL_EDGE
|
FILL_EDGE*
|
||||||
FASTCALL
|
FASTCALL
|
||||||
POLYGONFILL_MakeEdge(POINT From, POINT To)
|
POLYGONFILL_MakeEdge(POINT From, POINT To)
|
||||||
{
|
{
|
||||||
int absdx, absdy;
|
FILL_EDGE* rc = (FILL_EDGE*)EngAllocMem(FL_ZERO_MEMORY, sizeof(FILL_EDGE), FILL_EDGE_ALLOC_TAG);
|
||||||
PPFILL_EDGE rc = (PPFILL_EDGE)EngAllocMem(FL_ZERO_MEMORY, sizeof(PFILL_EDGE), PFILL_EDGE_ALLOC_TAG);
|
|
||||||
|
|
||||||
if (0 == rc)
|
if (0 == rc)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
//DPRINT ("Making Edge: (%d, %d) to (%d, %d)\n", From.x, From.y, To.x, To.y);
|
//DPRINT1("Making Edge: (%d, %d) to (%d, %d)\n", From.x, From.y, To.x, To.y);
|
||||||
//Now Fill the struct.
|
//Now Fill the struct.
|
||||||
if ( To.y < From.y )
|
if ( To.y < From.y )
|
||||||
{
|
{
|
||||||
|
@ -166,22 +153,16 @@ POLYGONFILL_MakeEdge(POINT From, POINT To)
|
||||||
rc->YDirection = 1;
|
rc->YDirection = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc->x = rc->FromX;
|
||||||
|
rc->y = rc->FromY;
|
||||||
rc->dx = rc->ToX - rc->FromX;
|
rc->dx = rc->ToX - rc->FromX;
|
||||||
rc->dy = rc->ToY - rc->FromY;
|
rc->dy = rc->ToY - rc->FromY;
|
||||||
absdx = abs(rc->dx);
|
rc->absdx = abs(rc->dx);
|
||||||
absdy = abs(rc->dy);
|
rc->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);
|
|
||||||
|
|
||||||
if (rc->MinY == To.y)
|
rc->xmajor = rc->absdx > rc->absdy;
|
||||||
rc->XIntercept = To.x;
|
|
||||||
else
|
|
||||||
rc->XIntercept = From.x;
|
|
||||||
|
|
||||||
rc->ErrorMax = absdy;
|
rc->ErrorMax = MAX(rc->absdx,rc->absdy);
|
||||||
rc->ErrorInc = absdx;
|
|
||||||
|
|
||||||
rc->Error = rc->ErrorMax / 2;
|
rc->Error = rc->ErrorMax / 2;
|
||||||
|
|
||||||
|
@ -189,8 +170,25 @@ POLYGONFILL_MakeEdge(POINT From, POINT To)
|
||||||
|
|
||||||
rc->pNext = 0;
|
rc->pNext = 0;
|
||||||
|
|
||||||
DPRINT ("MakeEdge (%i,%i)->(%i,%i) d=(%i,%i) dir=%i err=%i max=%i\n",
|
rc->XIntercept[0] = rc->x;
|
||||||
From.x, From.y, To.x, To.y, rc->dx, rc->dy, rc->Direction, rc->Error, rc->ErrorMax );
|
rc->XIntercept[1] = rc->x;
|
||||||
|
|
||||||
|
if ( rc->xmajor && rc->absdy )
|
||||||
|
{
|
||||||
|
int x1 = rc->x;
|
||||||
|
int steps = (rc->ErrorMax-rc->Error-1) / rc->absdy;
|
||||||
|
if ( steps )
|
||||||
|
{
|
||||||
|
rc->x += steps * rc->XDirection;
|
||||||
|
rc->Error += steps * rc->absdy;
|
||||||
|
ASSERT ( rc->Error < rc->ErrorMax );
|
||||||
|
rc->XIntercept[0] = MIN(x1,rc->x);
|
||||||
|
rc->XIntercept[1] = MAX(x1,rc->x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -211,30 +209,12 @@ POLYGONFILL_MakeEdge(POINT From, POINT To)
|
||||||
static
|
static
|
||||||
INT
|
INT
|
||||||
FASTCALL
|
FASTCALL
|
||||||
PFILL_EDGE_Compare(PPFILL_EDGE Edge1, PPFILL_EDGE Edge2)
|
FILL_EDGE_Compare(FILL_EDGE* Edge1, FILL_EDGE* Edge2)
|
||||||
{
|
{
|
||||||
//DPRINT("In PFILL_EDGE_Compare()\n");
|
int e1 = Edge1->XIntercept[0] + Edge1->XIntercept[1];
|
||||||
if (Edge1->MinY == Edge2->MinY)
|
int e2 = Edge2->XIntercept[0] + Edge2->XIntercept[1];
|
||||||
{
|
|
||||||
//DPRINT("In PFILL_EDGE_Compare() MinYs are equal\n");
|
return e1 - e2;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//DPRINT("In PFILL_EDGE_Compare() returning: %d\n",Edge1->MinY - Edge2->MinY);
|
|
||||||
return Edge1->MinY - Edge2->MinY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -244,79 +224,91 @@ PFILL_EDGE_Compare(PPFILL_EDGE Edge1, PPFILL_EDGE Edge2)
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
FASTCALL
|
FASTCALL
|
||||||
POLYGONFILL_ListInsert(PFILL_EDGE_LIST *list, PPFILL_EDGE NewEdge)
|
POLYGONFILL_ActiveListInsert(FILL_EDGE** activehead, FILL_EDGE* NewEdge )
|
||||||
{
|
{
|
||||||
PPFILL_EDGE pThis;
|
FILL_EDGE *pPrev, *pThis;
|
||||||
if (0 != list && 0 != NewEdge)
|
//DPRINT1("In POLYGONFILL_ActiveListInsert()\n");
|
||||||
|
ASSERT ( activehead && NewEdge );
|
||||||
|
if ( !*activehead )
|
||||||
{
|
{
|
||||||
pThis = *list;
|
NewEdge->pNext = NULL;
|
||||||
//DPRINT("In POLYGONFILL_ListInsert()\n");
|
*activehead = 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);
|
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
** 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Create a list of edges for a list of points.
|
** Create a list of edges for a list of points.
|
||||||
*/
|
*/
|
||||||
static
|
static
|
||||||
PFILL_EDGE_LIST
|
FILL_EDGE_LIST*
|
||||||
FASTCALL
|
FASTCALL
|
||||||
POLYGONFILL_MakeEdgeList(PPOINT Points, int Count)
|
POLYGONFILL_MakeEdgeList(PPOINT Points, int Count)
|
||||||
{
|
{
|
||||||
int CurPt = 0;
|
int CurPt = 0;
|
||||||
int SeqNum = 0;
|
FILL_EDGE_LIST* list = 0;
|
||||||
PPFILL_EDGE rc = 0;
|
FILL_EDGE* e = 0;
|
||||||
PPFILL_EDGE NextEdge = 0;
|
|
||||||
|
|
||||||
if ( 0 == Points || 2 > Count )
|
if ( 0 == Points || 2 > Count )
|
||||||
return rc;
|
return 0;
|
||||||
|
|
||||||
//Establish the list with the first two points.
|
list = (FILL_EDGE_LIST*)EngAllocMem(FL_ZERO_MEMORY, sizeof(FILL_EDGE_LIST), FILL_EDGE_ALLOC_TAG);
|
||||||
rc = POLYGONFILL_MakeEdge ( Points[0], Points[1] );
|
if ( 0 == list )
|
||||||
if (0 == rc) return rc;
|
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,++SeqNum )
|
for ( CurPt = 1; CurPt < Count; ++CurPt )
|
||||||
{
|
{
|
||||||
if (CurPt == Count - 1 )
|
e = POLYGONFILL_MakeEdge ( Points[CurPt-1], Points[CurPt] );
|
||||||
{
|
if ( !e )
|
||||||
NextEdge = POLYGONFILL_MakeEdge(Points[CurPt],Points[0]);
|
goto fail;
|
||||||
}
|
// if a straight horizontal line - who cares?
|
||||||
|
if ( !e->absdy )
|
||||||
|
EngFreeMem ( e );
|
||||||
else
|
else
|
||||||
{
|
list->Edges[list->Count++] = e;
|
||||||
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;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -329,187 +321,88 @@ POLYGONFILL_MakeEdgeList(PPOINT Points, int Count)
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
FASTCALL
|
FASTCALL
|
||||||
POLYGONFILL_UpdateScanline(PPFILL_EDGE pEdge, int Scanline)
|
POLYGONFILL_UpdateScanline(FILL_EDGE* pEdge, int Scanline)
|
||||||
{
|
{
|
||||||
if ( 0 == pEdge->dy )
|
if ( 0 == pEdge->dy )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ( pEdge->ErrorMax )
|
ASSERT ( pEdge->FromY < Scanline && pEdge->ToY >= Scanline );
|
||||||
|
|
||||||
|
if ( pEdge->xmajor )
|
||||||
{
|
{
|
||||||
pEdge->Error += pEdge->ErrorInc;
|
int steps;
|
||||||
|
// we should require exactly 1 step to step onto current 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 current scanline...
|
||||||
|
pEdge->Error -= pEdge->absdx;
|
||||||
|
pEdge->y++;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // then this is a y-major line
|
||||||
|
{
|
||||||
|
pEdge->Error += pEdge->absdx;
|
||||||
|
pEdge->y++;
|
||||||
|
|
||||||
if ( pEdge->Error >= pEdge->ErrorMax )
|
if ( pEdge->Error >= pEdge->ErrorMax )
|
||||||
{
|
{
|
||||||
int steps = pEdge->Error / pEdge->ErrorMax;
|
pEdge->Error -= pEdge->ErrorMax;
|
||||||
pEdge->XIntercept += steps * pEdge->XDirection;
|
pEdge->x += pEdge->XDirection;
|
||||||
pEdge->Error -= steps * pEdge->ErrorMax;
|
ASSERT ( pEdge->Error < pEdge->ErrorMax );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pEdge->XIntercept[0] = pEdge->x;
|
||||||
|
pEdge->XIntercept[1] = pEdge->x;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT ("Line (%d, %d) to (%d, %d) intersects scanline %d at %d\n",
|
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 );
|
pEdge->FromX, pEdge->FromY, pEdge->ToX, pEdge->ToY, Scanline, pEdge->XIntercept[0], pEdge->XIntercept[1] );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
** This routine removes an edge from the global edge list and inserts it into
|
|
||||||
** the active edge list (preserving the order).
|
|
||||||
** An edge is considered Active if the current scanline intersects it.
|
|
||||||
**
|
|
||||||
** Note: once an edge is no longer active, it is deleted.
|
|
||||||
*/
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
/*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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** 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)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
/*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.
|
** This method updates the Active edge collection for the scanline Scanline.
|
||||||
*/
|
*/
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
STDCALL
|
STDCALL
|
||||||
POLYGONFILL_UpdateActiveEdges(int Scanline, PFILL_EDGE_LIST *GEC, PFILL_EDGE_LIST *AEC)
|
POLYGONFILL_BuildActiveList ( int Scanline, FILL_EDGE_LIST* list, FILL_EDGE** ActiveHead )
|
||||||
{
|
{
|
||||||
PPFILL_EDGE pThis = 0;
|
int i;
|
||||||
PPFILL_EDGE pAECLast = 0;
|
|
||||||
PPFILL_EDGE pPrev = 0;
|
ASSERT ( list && ActiveHead );
|
||||||
DPRINT("In POLYGONFILL_UpdateActiveEdges() Scanline: %d\n", Scanline);
|
*ActiveHead = 0;
|
||||||
/*First scan through GEC and look for any edges that have become active*/
|
for ( i = 0; i < list->Count; i++ )
|
||||||
pThis = *GEC;
|
|
||||||
while (0 != pThis && pThis->MinY <= Scanline)
|
|
||||||
{
|
{
|
||||||
//DPRINT("Moving Edge to AEC\n");
|
FILL_EDGE* pEdge = list->Edges[i];
|
||||||
/*Remove the edge from GEC and put it into AEC*/
|
ASSERT(pEdge);
|
||||||
if (pThis->MinY <= Scanline)
|
if ( pEdge->FromY < Scanline && pEdge->ToY >= Scanline )
|
||||||
{
|
{
|
||||||
/*Always peel off the front of the GEC*/
|
POLYGONFILL_UpdateScanline ( pEdge, Scanline );
|
||||||
*GEC = pThis->pNext;
|
POLYGONFILL_ActiveListInsert ( ActiveHead, pEdge );
|
||||||
|
|
||||||
/*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;
|
|
||||||
}
|
|
||||||
/*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("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*/
|
|
||||||
POLYGONFILL_AECReorder(AEC);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -519,138 +412,137 @@ POLYGONFILL_UpdateActiveEdges(int Scanline, PFILL_EDGE_LIST *GEC, PFILL_EDGE_LIS
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
STDCALL
|
STDCALL
|
||||||
POLYGONFILL_FillScanLineAlternate(PDC dc, int ScanLine, PFILL_EDGE_LIST ActiveEdges, SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX RopMode)
|
POLYGONFILL_FillScanLineAlternate(
|
||||||
|
PDC dc,
|
||||||
|
int ScanLine,
|
||||||
|
FILL_EDGE* ActiveHead,
|
||||||
|
SURFOBJ *SurfObj,
|
||||||
|
PBRUSHOBJ BrushObj,
|
||||||
|
MIX RopMode )
|
||||||
{
|
{
|
||||||
BOOL OnOdd = TRUE;
|
FILL_EDGE *pLeft, *pRight;
|
||||||
RECTL BoundRect;
|
|
||||||
int XInterceptOdd,XInterceptEven,ret;
|
|
||||||
PPFILL_EDGE pThis = ActiveEdges;
|
|
||||||
|
|
||||||
while (NULL != pThis)
|
if ( !ActiveHead )
|
||||||
|
return;
|
||||||
|
|
||||||
|
pLeft = ActiveHead;
|
||||||
|
pRight = pLeft->pNext;
|
||||||
|
ASSERT(pRight);
|
||||||
|
|
||||||
|
while ( NULL != pRight )
|
||||||
{
|
{
|
||||||
if (OnOdd)
|
int x1 = pLeft->XIntercept[1];
|
||||||
|
int x2 = pRight->XIntercept[0]+1;
|
||||||
|
if ( x2 > x1 )
|
||||||
{
|
{
|
||||||
XInterceptOdd = pThis->XIntercept;
|
RECTL BoundRect;
|
||||||
OnOdd = FALSE;
|
BoundRect.top = ScanLine;
|
||||||
}
|
BoundRect.bottom = ScanLine + 1;
|
||||||
else
|
BoundRect.left = x1;
|
||||||
{
|
BoundRect.right = x2;
|
||||||
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);
|
DPRINT("Fill Line (%d, %d) to (%d, %d)\n",x1, ScanLine, x2, ScanLine);
|
||||||
ret = IntEngLineTo( SurfObj,
|
IntEngLineTo( SurfObj,
|
||||||
dc->CombinedClip,
|
dc->CombinedClip,
|
||||||
BrushObj,
|
BrushObj,
|
||||||
XInterceptOdd,
|
x1,
|
||||||
ScanLine,
|
ScanLine,
|
||||||
XInterceptEven,
|
x2,
|
||||||
ScanLine,
|
ScanLine,
|
||||||
&BoundRect, /* Bounding rectangle */
|
&BoundRect, // Bounding rectangle
|
||||||
RopMode); /* MIX */
|
RopMode); // MIX
|
||||||
}
|
|
||||||
OnOdd = TRUE;
|
|
||||||
}
|
}
|
||||||
pThis = pThis->pNext;
|
pLeft = pRight->pNext;
|
||||||
|
pRight = pLeft ? pLeft->pNext : NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
STDCALL
|
STDCALL
|
||||||
POLYGONFILL_FillScanLineWinding(PDC dc, int ScanLine, PFILL_EDGE_LIST ActiveEdges, SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX RopMode)
|
POLYGONFILL_FillScanLineWinding(
|
||||||
|
PDC dc,
|
||||||
|
int ScanLine,
|
||||||
|
FILL_EDGE* ActiveHead,
|
||||||
|
SURFOBJ *SurfObj,
|
||||||
|
PBRUSHOBJ BrushObj,
|
||||||
|
MIX RopMode )
|
||||||
{
|
{
|
||||||
RECTL BoundRect;
|
FILL_EDGE *pLeft, *pRight;
|
||||||
int XPrevIntercept,XIntercept,ret;
|
|
||||||
PPFILL_EDGE pThis = ActiveEdges;
|
|
||||||
int winding = 0;
|
int winding = 0;
|
||||||
|
|
||||||
XPrevIntercept = pThis->XIntercept;
|
if ( !ActiveHead )
|
||||||
winding += pThis->YDirection;
|
return;
|
||||||
pThis = pThis->pNext;
|
|
||||||
|
|
||||||
while (NULL != pThis)
|
pLeft = ActiveHead;
|
||||||
|
winding = pLeft->YDirection;
|
||||||
|
pRight = pLeft->pNext;
|
||||||
|
ASSERT(pRight);
|
||||||
|
|
||||||
|
while ( NULL != pRight )
|
||||||
{
|
{
|
||||||
XIntercept = pThis->XIntercept + 1;
|
int x1 = pLeft->XIntercept[1];
|
||||||
if ( winding && XIntercept > XPrevIntercept )
|
int x2 = pRight->XIntercept[0]+1;
|
||||||
|
if ( winding && x2 > x1 )
|
||||||
{
|
{
|
||||||
|
RECTL BoundRect;
|
||||||
BoundRect.top = ScanLine;
|
BoundRect.top = ScanLine;
|
||||||
BoundRect.bottom = ScanLine + 1;
|
BoundRect.bottom = ScanLine + 1;
|
||||||
BoundRect.left = XPrevIntercept;
|
BoundRect.left = x1;
|
||||||
BoundRect.right = XIntercept;
|
BoundRect.right = x2;
|
||||||
|
|
||||||
DPRINT ("Fill Line (%d, %d) to (%d, %d)\n",XPrevIntercept, ScanLine, XIntercept, ScanLine);
|
DPRINT("Fill Line (%d, %d) to (%d, %d)\n",x1, ScanLine, x2, ScanLine);
|
||||||
ret = IntEngLineTo( SurfObj,
|
IntEngLineTo( SurfObj,
|
||||||
dc->CombinedClip,
|
dc->CombinedClip,
|
||||||
BrushObj,
|
BrushObj,
|
||||||
XPrevIntercept,
|
x1,
|
||||||
ScanLine,
|
ScanLine,
|
||||||
XIntercept,
|
x2,
|
||||||
ScanLine,
|
ScanLine,
|
||||||
&BoundRect, // Bounding rectangle
|
&BoundRect, // Bounding rectangle
|
||||||
RopMode); // MIX
|
RopMode); // MIX
|
||||||
}
|
}
|
||||||
XPrevIntercept = XIntercept - 1;
|
pLeft = pRight;
|
||||||
winding += pThis->YDirection;
|
pRight = pLeft->pNext;
|
||||||
pThis = pThis->pNext;
|
winding += pLeft->YDirection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//ALTERNATE Selects alternate mode (fills the area between odd-numbered and even-numbered
|
|
||||||
//polygon sides on each scan line).
|
|
||||||
//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)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
/* 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_FillScanLineAlternate(dc, ScanLine, ActiveEdges, SurfObj, BrushObj, RopMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free Edge List. If any are left. */
|
|
||||||
POLYGONFILL_DestroyEdgeList(list);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
//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.
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
STDCALL
|
STDCALL
|
||||||
FillPolygon_WINDING(PDC dc, SURFOBJ *SurfObj, PBRUSHOBJ BrushObj,MIX RopMode, CONST PPOINT Points, int Count, RECTL BoundRect)
|
FillPolygon(
|
||||||
|
PDC dc,
|
||||||
|
SURFOBJ *SurfObj,
|
||||||
|
PBRUSHOBJ BrushObj,
|
||||||
|
MIX RopMode,
|
||||||
|
CONST PPOINT Points,
|
||||||
|
int Count,
|
||||||
|
RECTL BoundRect )
|
||||||
{
|
{
|
||||||
PFILL_EDGE_LIST list = 0;
|
FILL_EDGE_LIST *list = 0;
|
||||||
PFILL_EDGE_LIST ActiveEdges = 0;
|
FILL_EDGE *ActiveHead = 0;
|
||||||
int ScanLine;
|
int ScanLine;
|
||||||
|
|
||||||
DPRINT("FillPolygon_ALTERNATE\n");
|
void
|
||||||
|
STDCALL
|
||||||
|
(*FillScanLine)(
|
||||||
|
PDC dc,
|
||||||
|
int ScanLine,
|
||||||
|
FILL_EDGE* ActiveHead,
|
||||||
|
SURFOBJ *SurfObj,
|
||||||
|
PBRUSHOBJ BrushObj,
|
||||||
|
MIX RopMode );
|
||||||
|
|
||||||
|
DPRINT("FillPolygon\n");
|
||||||
|
|
||||||
/* Create Edge List. */
|
/* Create Edge List. */
|
||||||
list = POLYGONFILL_MakeEdgeList(Points, Count);
|
list = POLYGONFILL_MakeEdgeList(Points, Count);
|
||||||
|
@ -658,14 +550,19 @@ FillPolygon_WINDING(PDC dc, SURFOBJ *SurfObj, PBRUSHOBJ BrushObj,MIX RopMode, CO
|
||||||
if (NULL == list)
|
if (NULL == list)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
if ( WINDING == dc->w.polyFillMode )
|
||||||
|
FillScanLine = POLYGONFILL_FillScanLineWinding;
|
||||||
|
else /* default */
|
||||||
|
FillScanLine = POLYGONFILL_FillScanLineAlternate;
|
||||||
|
|
||||||
/* 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_BuildActiveList(ScanLine, list, &ActiveHead);
|
||||||
/* DEBUG_PRINT_EDGELIST(ActiveEdges); */
|
//DEBUG_PRINT_ACTIVE_EDGELIST(ActiveHead);
|
||||||
POLYGONFILL_FillScanLineWinding(dc, ScanLine, ActiveEdges, SurfObj, BrushObj, RopMode);
|
FillScanLine ( dc, ScanLine, ActiveHead, SurfObj, BrushObj, RopMode );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free Edge List. If any are left. */
|
/* Free Edge List. If any are left. */
|
||||||
|
|
Loading…
Reference in a new issue