gdi32: Convert the edges list to a standard list in CreatePolyPolygonRgn.
This commit is contained in:
parent
6a9b775f36
commit
31f0079f1c
@ -351,26 +351,19 @@ static inline void bres_incr_polygon( struct bres_info *bres )
|
|||||||
* drawn (as with the even-odd rule).
|
* drawn (as with the even-odd rule).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
typedef struct edge_table_entry {
|
||||||
* for the winding number rule
|
struct list entry;
|
||||||
*/
|
struct list winding_entry;
|
||||||
#define CLOCKWISE 1
|
INT ymax; /* ycoord at which we exit this edge. */
|
||||||
#define COUNTERCLOCKWISE -1
|
struct bres_info bres; /* Bresenham info to run the edge */
|
||||||
|
int ClockWise; /* flag for winding number rule */
|
||||||
typedef struct _EdgeTableEntry {
|
|
||||||
INT ymax; /* ycoord at which we exit this edge. */
|
|
||||||
struct bres_info bres; /* Bresenham info to run the edge */
|
|
||||||
struct _EdgeTableEntry *next; /* next in the list */
|
|
||||||
struct _EdgeTableEntry *back; /* for insertion sort */
|
|
||||||
struct _EdgeTableEntry *nextWETE; /* for winding num rule */
|
|
||||||
int ClockWise; /* flag for winding number rule */
|
|
||||||
} EdgeTableEntry;
|
} EdgeTableEntry;
|
||||||
|
|
||||||
|
|
||||||
typedef struct _ScanLineList{
|
typedef struct _ScanLineList{
|
||||||
INT scanline; /* the scanline represented */
|
struct list edgelist;
|
||||||
EdgeTableEntry *edgelist; /* header node */
|
INT scanline; /* the scanline represented */
|
||||||
struct _ScanLineList *next; /* next in the list */
|
struct _ScanLineList *next; /* next in the list */
|
||||||
} ScanLineList;
|
} ScanLineList;
|
||||||
|
|
||||||
|
|
||||||
@ -394,56 +387,6 @@ typedef struct _ScanLineListBlock {
|
|||||||
} ScanLineListBlock;
|
} ScanLineListBlock;
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* a few macros for the inner loops of the fill code where
|
|
||||||
* performance considerations don't allow a procedure call.
|
|
||||||
*
|
|
||||||
* Evaluate the given edge at the given scanline.
|
|
||||||
* If the edge has expired, then we leave it and fix up
|
|
||||||
* the active edge table; otherwise, we increment the
|
|
||||||
* x value to be ready for the next scanline.
|
|
||||||
* The winding number rule is in effect, so we must notify
|
|
||||||
* the caller when the edge has been removed so he
|
|
||||||
* can reorder the Winding Active Edge Table.
|
|
||||||
*/
|
|
||||||
#define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) { \
|
|
||||||
if (pAET->ymax == y) { /* leaving this edge */ \
|
|
||||||
pPrevAET->next = pAET->next; \
|
|
||||||
pAET = pPrevAET->next; \
|
|
||||||
fixWAET = 1; \
|
|
||||||
if (pAET) \
|
|
||||||
pAET->back = pPrevAET; \
|
|
||||||
} \
|
|
||||||
else { \
|
|
||||||
bres_incr_polygon(&pAET->bres); \
|
|
||||||
pPrevAET = pAET; \
|
|
||||||
pAET = pAET->next; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Evaluate the given edge at the given scanline.
|
|
||||||
* If the edge has expired, then we leave it and fix up
|
|
||||||
* the active edge table; otherwise, we increment the
|
|
||||||
* x value to be ready for the next scanline.
|
|
||||||
* The even-odd rule is in effect.
|
|
||||||
*/
|
|
||||||
#define EVALUATEEDGEEVENODD(pAET, pPrevAET, y) { \
|
|
||||||
if (pAET->ymax == y) { /* leaving this edge */ \
|
|
||||||
pPrevAET->next = pAET->next; \
|
|
||||||
pAET = pPrevAET->next; \
|
|
||||||
if (pAET) \
|
|
||||||
pAET->back = pPrevAET; \
|
|
||||||
} \
|
|
||||||
else { \
|
|
||||||
bres_incr_polygon(&pAET->bres); \
|
|
||||||
pPrevAET = pAET; \
|
|
||||||
pAET = pAET->next; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note the parameter order is different from the X11 equivalents */
|
/* Note the parameter order is different from the X11 equivalents */
|
||||||
|
|
||||||
static BOOL REGION_CopyRegion(WINEREGION *d, WINEREGION *s);
|
static BOOL REGION_CopyRegion(WINEREGION *d, WINEREGION *s);
|
||||||
@ -2376,7 +2319,7 @@ static void REGION_InsertEdgeInET(EdgeTable *ET, EdgeTableEntry *ETE,
|
|||||||
INT scanline, ScanLineListBlock **SLLBlock, INT *iSLLBlock)
|
INT scanline, ScanLineListBlock **SLLBlock, INT *iSLLBlock)
|
||||||
|
|
||||||
{
|
{
|
||||||
EdgeTableEntry *start, *prev;
|
struct list *ptr;
|
||||||
ScanLineList *pSLL, *pPrevSLL;
|
ScanLineList *pSLL, *pPrevSLL;
|
||||||
ScanLineListBlock *tmpSLLBlock;
|
ScanLineListBlock *tmpSLLBlock;
|
||||||
|
|
||||||
@ -2412,7 +2355,7 @@ static void REGION_InsertEdgeInET(EdgeTable *ET, EdgeTableEntry *ETE,
|
|||||||
pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]);
|
pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]);
|
||||||
|
|
||||||
pSLL->next = pPrevSLL->next;
|
pSLL->next = pPrevSLL->next;
|
||||||
pSLL->edgelist = NULL;
|
list_init( &pSLL->edgelist );
|
||||||
pPrevSLL->next = pSLL;
|
pPrevSLL->next = pSLL;
|
||||||
}
|
}
|
||||||
pSLL->scanline = scanline;
|
pSLL->scanline = scanline;
|
||||||
@ -2420,19 +2363,12 @@ static void REGION_InsertEdgeInET(EdgeTable *ET, EdgeTableEntry *ETE,
|
|||||||
/*
|
/*
|
||||||
* now insert the edge in the right bucket
|
* now insert the edge in the right bucket
|
||||||
*/
|
*/
|
||||||
prev = NULL;
|
LIST_FOR_EACH( ptr, &pSLL->edgelist )
|
||||||
start = pSLL->edgelist;
|
|
||||||
while (start && (start->bres.minor_axis < ETE->bres.minor_axis))
|
|
||||||
{
|
{
|
||||||
prev = start;
|
struct edge_table_entry *entry = LIST_ENTRY( ptr, struct edge_table_entry, entry );
|
||||||
start = start->next;
|
if (entry->bres.minor_axis >= ETE->bres.minor_axis) break;
|
||||||
}
|
}
|
||||||
ETE->next = start;
|
list_add_before( ptr, &ETE->entry );
|
||||||
|
|
||||||
if (prev)
|
|
||||||
prev->next = ETE;
|
|
||||||
else
|
|
||||||
pSLL->edgelist = ETE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
@ -2459,8 +2395,8 @@ static void REGION_InsertEdgeInET(EdgeTable *ET, EdgeTableEntry *ETE,
|
|||||||
* which an edge is initially entered.
|
* which an edge is initially entered.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void REGION_CreateETandAET(const INT *Count, INT nbpolygons,
|
static void REGION_CreateEdgeTable(const INT *Count, INT nbpolygons,
|
||||||
const POINT *pts, EdgeTable *ET, EdgeTableEntry *AET,
|
const POINT *pts, EdgeTable *ET,
|
||||||
EdgeTableEntry *pETEs, ScanLineListBlock *pSLLBlock)
|
EdgeTableEntry *pETEs, ScanLineListBlock *pSLLBlock)
|
||||||
{
|
{
|
||||||
const POINT *top, *bottom;
|
const POINT *top, *bottom;
|
||||||
@ -2469,15 +2405,6 @@ static void REGION_CreateETandAET(const INT *Count, INT nbpolygons,
|
|||||||
int iSLLBlock = 0;
|
int iSLLBlock = 0;
|
||||||
int dy;
|
int dy;
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* initialize the Active Edge Table
|
|
||||||
*/
|
|
||||||
AET->next = NULL;
|
|
||||||
AET->back = NULL;
|
|
||||||
AET->nextWETE = NULL;
|
|
||||||
AET->bres.minor_axis = SMALL_COORDINATE;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* initialize the Edge Table.
|
* initialize the Edge Table.
|
||||||
*/
|
*/
|
||||||
@ -2556,29 +2483,20 @@ static void REGION_CreateETandAET(const INT *Count, INT nbpolygons,
|
|||||||
* leaving them sorted by smaller x coordinate.
|
* leaving them sorted by smaller x coordinate.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void REGION_loadAET(EdgeTableEntry *AET, EdgeTableEntry *ETEs)
|
static void REGION_loadAET( struct list *AET, struct list *ETEs )
|
||||||
{
|
{
|
||||||
EdgeTableEntry *pPrevAET;
|
struct edge_table_entry *ptr, *next, *entry;
|
||||||
EdgeTableEntry *tmp;
|
struct list *active;
|
||||||
|
|
||||||
pPrevAET = AET;
|
LIST_FOR_EACH_ENTRY_SAFE( ptr, next, ETEs, struct edge_table_entry, entry )
|
||||||
AET = AET->next;
|
|
||||||
while (ETEs)
|
|
||||||
{
|
{
|
||||||
while (AET && (AET->bres.minor_axis < ETEs->bres.minor_axis))
|
LIST_FOR_EACH( active, AET )
|
||||||
{
|
{
|
||||||
pPrevAET = AET;
|
entry = LIST_ENTRY( active, struct edge_table_entry, entry );
|
||||||
AET = AET->next;
|
if (entry->bres.minor_axis >= ptr->bres.minor_axis) break;
|
||||||
}
|
}
|
||||||
tmp = ETEs->next;
|
list_remove( &ptr->entry );
|
||||||
ETEs->next = AET;
|
list_add_before( active, &ptr->entry );
|
||||||
if (AET)
|
|
||||||
AET->back = ETEs;
|
|
||||||
ETEs->back = pPrevAET;
|
|
||||||
pPrevAET->next = ETEs;
|
|
||||||
pPrevAET = ETEs;
|
|
||||||
|
|
||||||
ETEs = tmp;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2602,70 +2520,50 @@ static void REGION_loadAET(EdgeTableEntry *AET, EdgeTableEntry *ETEs)
|
|||||||
* V-------------------> V---> ...
|
* V-------------------> V---> ...
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void REGION_computeWAET(EdgeTableEntry *AET)
|
static void REGION_computeWAET( struct list *AET, struct list *WETE )
|
||||||
{
|
{
|
||||||
EdgeTableEntry *pWETE;
|
struct edge_table_entry *active;
|
||||||
int inside = 1;
|
int inside = 1;
|
||||||
int isInside = 0;
|
int isInside = 0;
|
||||||
|
|
||||||
AET->nextWETE = NULL;
|
list_init( WETE );
|
||||||
pWETE = AET;
|
LIST_FOR_EACH_ENTRY( active, AET, struct edge_table_entry, entry )
|
||||||
AET = AET->next;
|
|
||||||
while (AET)
|
|
||||||
{
|
{
|
||||||
if (AET->ClockWise)
|
if (active->ClockWise)
|
||||||
isInside++;
|
isInside++;
|
||||||
else
|
else
|
||||||
isInside--;
|
isInside--;
|
||||||
|
|
||||||
if ((!inside && !isInside) ||
|
if ((!inside && !isInside) || (inside && isInside))
|
||||||
( inside && isInside))
|
|
||||||
{
|
{
|
||||||
pWETE->nextWETE = AET;
|
list_add_tail( WETE, &active->winding_entry );
|
||||||
pWETE = AET;
|
|
||||||
inside = !inside;
|
inside = !inside;
|
||||||
}
|
}
|
||||||
AET = AET->next;
|
|
||||||
}
|
}
|
||||||
pWETE->nextWETE = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* REGION_InsertionSort
|
* REGION_InsertionSort
|
||||||
*
|
*
|
||||||
* Just a simple insertion sort using
|
* Just a simple insertion sort to sort the Active Edge Table.
|
||||||
* pointers and back pointers to sort the Active
|
|
||||||
* Edge Table.
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static BOOL REGION_InsertionSort(EdgeTableEntry *AET)
|
static BOOL REGION_InsertionSort( struct list *AET )
|
||||||
{
|
{
|
||||||
EdgeTableEntry *pETEchase;
|
struct edge_table_entry *active, *next, *insert;
|
||||||
EdgeTableEntry *pETEinsert;
|
|
||||||
EdgeTableEntry *pETEchaseBackTMP;
|
|
||||||
BOOL changed = FALSE;
|
BOOL changed = FALSE;
|
||||||
|
|
||||||
AET = AET->next;
|
LIST_FOR_EACH_ENTRY_SAFE( active, next, AET, struct edge_table_entry, entry )
|
||||||
while (AET)
|
|
||||||
{
|
{
|
||||||
pETEinsert = AET;
|
LIST_FOR_EACH_ENTRY( insert, AET, struct edge_table_entry, entry )
|
||||||
pETEchase = AET;
|
|
||||||
while (pETEchase->back->bres.minor_axis > AET->bres.minor_axis)
|
|
||||||
pETEchase = pETEchase->back;
|
|
||||||
|
|
||||||
AET = AET->next;
|
|
||||||
if (pETEchase != pETEinsert)
|
|
||||||
{
|
{
|
||||||
pETEchaseBackTMP = pETEchase->back;
|
if (insert == active) break;
|
||||||
pETEinsert->back->next = AET;
|
if (insert->bres.minor_axis > active->bres.minor_axis) break;
|
||||||
if (AET)
|
|
||||||
AET->back = pETEinsert->back;
|
|
||||||
pETEinsert->next = pETEchase;
|
|
||||||
pETEchase->back->next = pETEinsert;
|
|
||||||
pETEchase->back = pETEinsert;
|
|
||||||
pETEinsert->back = pETEchaseBackTMP;
|
|
||||||
changed = TRUE;
|
|
||||||
}
|
}
|
||||||
|
if (insert == active) continue;
|
||||||
|
list_remove( &active->entry );
|
||||||
|
list_add_before( &insert->entry, &active->entry );
|
||||||
|
changed = TRUE;
|
||||||
}
|
}
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
@ -2759,17 +2657,16 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count,
|
|||||||
{
|
{
|
||||||
HRGN hrgn = 0;
|
HRGN hrgn = 0;
|
||||||
WINEREGION *obj;
|
WINEREGION *obj;
|
||||||
EdgeTableEntry *pAET; /* Active Edge Table */
|
|
||||||
INT y; /* current scanline */
|
INT y; /* current scanline */
|
||||||
EdgeTableEntry *pWETE; /* Winding Edge Table Entry*/
|
struct list WETE, *pWETE; /* Winding Edge Table */
|
||||||
ScanLineList *pSLL; /* current scanLineList */
|
ScanLineList *pSLL; /* current scanLineList */
|
||||||
EdgeTableEntry *pPrevAET; /* ptr to previous AET */
|
|
||||||
EdgeTable ET; /* header node for ET */
|
EdgeTable ET; /* header node for ET */
|
||||||
EdgeTableEntry AET; /* header node for AET */
|
struct list AET; /* header for AET */
|
||||||
EdgeTableEntry *pETEs; /* EdgeTableEntries pool */
|
EdgeTableEntry *pETEs; /* EdgeTableEntries pool */
|
||||||
ScanLineListBlock SLLBlock; /* header for scanlinelist */
|
ScanLineListBlock SLLBlock; /* header for scanlinelist */
|
||||||
int fixWAET = FALSE;
|
int fixWAET = FALSE;
|
||||||
struct point_block FirstPtBlock, *block; /* PtBlock buffers */
|
struct point_block FirstPtBlock, *block; /* PtBlock buffers */
|
||||||
|
struct edge_table_entry *active, *next;
|
||||||
INT poly, total;
|
INT poly, total;
|
||||||
|
|
||||||
TRACE("%p, count %d, polygons %d, mode %d\n", Pts, *Count, nbpolygons, mode);
|
TRACE("%p, count %d, polygons %d, mode %d\n", Pts, *Count, nbpolygons, mode);
|
||||||
@ -2794,7 +2691,8 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count,
|
|||||||
if (! (pETEs = HeapAlloc( GetProcessHeap(), 0, sizeof(EdgeTableEntry) * total )))
|
if (! (pETEs = HeapAlloc( GetProcessHeap(), 0, sizeof(EdgeTableEntry) * total )))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
REGION_CreateETandAET(Count, nbpolygons, Pts, &ET, &AET, pETEs, &SLLBlock);
|
REGION_CreateEdgeTable(Count, nbpolygons, Pts, &ET, pETEs, &SLLBlock);
|
||||||
|
list_init( &AET );
|
||||||
pSLL = ET.scanlines.next;
|
pSLL = ET.scanlines.next;
|
||||||
block = &FirstPtBlock;
|
block = &FirstPtBlock;
|
||||||
FirstPtBlock.count = 0;
|
FirstPtBlock.count = 0;
|
||||||
@ -2810,19 +2708,19 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count,
|
|||||||
* get to the next edge.
|
* get to the next edge.
|
||||||
*/
|
*/
|
||||||
if (pSLL != NULL && y == pSLL->scanline) {
|
if (pSLL != NULL && y == pSLL->scanline) {
|
||||||
REGION_loadAET(&AET, pSLL->edgelist);
|
REGION_loadAET(&AET, &pSLL->edgelist);
|
||||||
pSLL = pSLL->next;
|
pSLL = pSLL->next;
|
||||||
}
|
}
|
||||||
pPrevAET = &AET;
|
|
||||||
pAET = AET.next;
|
|
||||||
|
|
||||||
/*
|
LIST_FOR_EACH_ENTRY_SAFE( active, next, &AET, struct edge_table_entry, entry )
|
||||||
* for each active edge
|
{
|
||||||
*/
|
block = add_point( block, active->bres.minor_axis, y );
|
||||||
while (pAET) {
|
|
||||||
block = add_point( block, pAET->bres.minor_axis, y );
|
|
||||||
if (!block) goto done;
|
if (!block) goto done;
|
||||||
EVALUATEEDGEEVENODD(pAET, pPrevAET, y);
|
|
||||||
|
if (active->ymax == y) /* leaving this edge */
|
||||||
|
list_remove( &active->entry );
|
||||||
|
else
|
||||||
|
bres_incr_polygon( &active->bres );
|
||||||
}
|
}
|
||||||
REGION_InsertionSort(&AET);
|
REGION_InsertionSort(&AET);
|
||||||
}
|
}
|
||||||
@ -2837,28 +2735,33 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count,
|
|||||||
* get to the next edge.
|
* get to the next edge.
|
||||||
*/
|
*/
|
||||||
if (pSLL != NULL && y == pSLL->scanline) {
|
if (pSLL != NULL && y == pSLL->scanline) {
|
||||||
REGION_loadAET(&AET, pSLL->edgelist);
|
REGION_loadAET(&AET, &pSLL->edgelist);
|
||||||
REGION_computeWAET(&AET);
|
REGION_computeWAET( &AET, &WETE );
|
||||||
pSLL = pSLL->next;
|
pSLL = pSLL->next;
|
||||||
}
|
}
|
||||||
pPrevAET = &AET;
|
pWETE = list_head( &WETE );
|
||||||
pAET = AET.next;
|
|
||||||
pWETE = pAET;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* for each active edge
|
* for each active edge
|
||||||
*/
|
*/
|
||||||
while (pAET) {
|
LIST_FOR_EACH_ENTRY_SAFE( active, next, &AET, struct edge_table_entry, entry )
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* add to the buffer only those edges that
|
* add to the buffer only those edges that
|
||||||
* are in the Winding active edge table.
|
* are in the Winding active edge table.
|
||||||
*/
|
*/
|
||||||
if (pWETE == pAET) {
|
if (pWETE == &active->winding_entry) {
|
||||||
block = add_point( block, pAET->bres.minor_axis, y );
|
block = add_point( block, active->bres.minor_axis, y );
|
||||||
if (!block) goto done;
|
if (!block) goto done;
|
||||||
pWETE = pWETE->nextWETE;
|
pWETE = list_next( &WETE, pWETE );
|
||||||
}
|
}
|
||||||
EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET);
|
if (active->ymax == y) /* leaving this edge */
|
||||||
|
{
|
||||||
|
list_remove( &active->entry );
|
||||||
|
fixWAET = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
bres_incr_polygon( &active->bres );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2866,7 +2769,7 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count,
|
|||||||
* we just resorted or have exited an edge.
|
* we just resorted or have exited an edge.
|
||||||
*/
|
*/
|
||||||
if (REGION_InsertionSort(&AET) || fixWAET) {
|
if (REGION_InsertionSort(&AET) || fixWAET) {
|
||||||
REGION_computeWAET(&AET);
|
REGION_computeWAET( &AET, &WETE );
|
||||||
fixWAET = FALSE;
|
fixWAET = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user