gdi32: Move the scan conversion to a helper function.

Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Huw Davies 2020-06-09 10:54:48 +01:00 committed by Alexandre Julliard
parent 1b33e0f72e
commit 31605eb417
1 changed files with 73 additions and 81 deletions

View File

@ -2583,67 +2583,25 @@ static void REGION_FreeStorage(ScanLineListBlock *pSLLBlock)
} }
} }
/*********************************************************************** static void scan_convert( WINEREGION *obj, EdgeTable *ET, INT mode, const RECT *clip_rect )
* create_polypolygon_region
*
* Helper for CreatePolyPolygonRgn.
*/
HRGN create_polypolygon_region( const POINT *Pts, const INT *Count, INT nbpolygons, INT mode,
const RECT *clip_rect )
{ {
HRGN hrgn = 0; struct list AET;
WINEREGION *obj = NULL; ScanLineList *pSLL;
INT y; /* current scanline */
struct list WETE, *pWETE; /* Winding Edge Table */
ScanLineList *pSLL; /* current scanLineList */
EdgeTable ET; /* header node for ET */
struct list AET; /* header for AET */
EdgeTableEntry *pETEs; /* EdgeTableEntries pool */
ScanLineListBlock SLLBlock; /* header for scanlinelist */
struct edge_table_entry *active; struct edge_table_entry *active;
unsigned int nb_points; INT i, y, first = 1, cur_band = 0, prev_band = 0;
int cur_band = 0, prev_band = 0;
INT i, poly, total, first = 1;
TRACE("%p, count %d, polygons %d, mode %d\n", Pts, *Count, nbpolygons, mode); if (clip_rect) ET->ymax = min( ET->ymax, clip_rect->bottom );
/* special case a rectangle */
if (((nbpolygons == 1) && ((*Count == 4) ||
((*Count == 5) && (Pts[4].x == Pts[0].x) && (Pts[4].y == Pts[0].y)))) &&
(((Pts[0].y == Pts[1].y) &&
(Pts[1].x == Pts[2].x) &&
(Pts[2].y == Pts[3].y) &&
(Pts[3].x == Pts[0].x)) ||
((Pts[0].x == Pts[1].x) &&
(Pts[1].y == Pts[2].y) &&
(Pts[2].x == Pts[3].x) &&
(Pts[3].y == Pts[0].y))))
return CreateRectRgn( min(Pts[0].x, Pts[2].x), min(Pts[0].y, Pts[2].y),
max(Pts[0].x, Pts[2].x), max(Pts[0].y, Pts[2].y) );
for(poly = total = 0; poly < nbpolygons; poly++)
total += Count[poly];
if (! (pETEs = HeapAlloc( GetProcessHeap(), 0, sizeof(EdgeTableEntry) * total )))
return 0;
nb_points = REGION_CreateEdgeTable( Count, nbpolygons, Pts, &ET, pETEs, &SLLBlock, clip_rect );
if (!(obj = alloc_region( nb_points / 2 )))
goto done;
if (clip_rect) ET.ymax = min( ET.ymax, clip_rect->bottom );
list_init( &AET ); list_init( &AET );
pSLL = ET.scanlines.next; pSLL = ET->scanlines.next;
if (mode != WINDING) {
/* if (mode != WINDING)
* for each scanline {
*/ for (y = ET->ymin; y < ET->ymax; y++)
for (y = ET.ymin; y < ET.ymax; y++) { {
/* /* Add a new edge to the active edge table when we get to the next edge. */
* Add a new edge to the active edge table when we if (pSLL != NULL && y == pSLL->scanline)
* get to the next edge. {
*/
if (pSLL != NULL && y == pSLL->scanline) {
REGION_loadAET(&AET, &pSLL->edgelist); REGION_loadAET(&AET, &pSLL->edgelist);
pSLL = pSLL->next; pSLL = pSLL->next;
} }
@ -2676,33 +2634,26 @@ HRGN create_polypolygon_region( const POINT *Pts, const INT *Count, INT nbpolygo
} }
} }
} }
else { else /* mode == WINDING */
/* {
* for each scanline struct list WETE, *pWETE;
*/
for (y = ET.ymin; y < ET.ymax; y++) { for (y = ET->ymin; y < ET->ymax; y++)
/* {
* Add a new edge to the active edge table when we /* Add a new edge to the active edge table when we 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, &WETE ); REGION_computeWAET( &AET, &WETE );
pSLL = pSLL->next; pSLL = pSLL->next;
} }
pWETE = list_head( &WETE ); pWETE = list_head( &WETE );
/*
* for each active edge
*/
if (!clip_rect || y >= clip_rect->top) if (!clip_rect || y >= clip_rect->top)
{ {
LIST_FOR_EACH_ENTRY( active, &AET, struct edge_table_entry, entry ) LIST_FOR_EACH_ENTRY( active, &AET, struct edge_table_entry, entry )
{ {
/* /* Add to the buffer only those edges that are in the Winding active edge table. */
* add to the buffer only those edges that
* are in the Winding active edge table.
*/
if (pWETE == &active->winding_entry) if (pWETE == &active->winding_entry)
{ {
if (first) if (first)
@ -2722,10 +2673,7 @@ HRGN create_polypolygon_region( const POINT *Pts, const INT *Count, INT nbpolygo
} }
} }
/* /* Recompute the winding active edge table if we just resorted or have exited an edge. */
* recompute the winding active edge table if
* we just resorted or have exited an edge.
*/
if (next_scanline( &AET, y )) REGION_computeWAET( &AET, &WETE ); if (next_scanline( &AET, y )) REGION_computeWAET( &AET, &WETE );
if (obj->numRects) if (obj->numRects)
@ -2736,7 +2684,7 @@ HRGN create_polypolygon_region( const POINT *Pts, const INT *Count, INT nbpolygo
} }
} }
assert( obj->numRects <= nb_points / 2 ); assert( obj->numRects <= obj->size );
if (obj->numRects) if (obj->numRects)
{ {
@ -2751,11 +2699,55 @@ HRGN create_polypolygon_region( const POINT *Pts, const INT *Count, INT nbpolygo
} }
} }
REGION_compact( obj ); REGION_compact( obj );
}
/***********************************************************************
* create_polypolygon_region
*
* Helper for CreatePolyPolygonRgn.
*/
HRGN create_polypolygon_region( const POINT *Pts, const INT *Count, INT nbpolygons, INT mode,
const RECT *clip_rect )
{
HRGN hrgn = 0;
WINEREGION *obj = NULL;
EdgeTable ET; /* header node for ET */
EdgeTableEntry *pETEs; /* EdgeTableEntries pool */
ScanLineListBlock SLLBlock; /* header for scanlinelist */
unsigned int nb_points;
INT poly, total;
TRACE("%p, count %d, polygons %d, mode %d\n", Pts, *Count, nbpolygons, mode);
/* special case a rectangle */
if (((nbpolygons == 1) && ((*Count == 4) ||
((*Count == 5) && (Pts[4].x == Pts[0].x) && (Pts[4].y == Pts[0].y)))) &&
(((Pts[0].y == Pts[1].y) &&
(Pts[1].x == Pts[2].x) &&
(Pts[2].y == Pts[3].y) &&
(Pts[3].x == Pts[0].x)) ||
((Pts[0].x == Pts[1].x) &&
(Pts[1].y == Pts[2].y) &&
(Pts[2].x == Pts[3].x) &&
(Pts[3].y == Pts[0].y))))
return CreateRectRgn( min(Pts[0].x, Pts[2].x), min(Pts[0].y, Pts[2].y),
max(Pts[0].x, Pts[2].x), max(Pts[0].y, Pts[2].y) );
for(poly = total = 0; poly < nbpolygons; poly++)
total += Count[poly];
if (! (pETEs = HeapAlloc( GetProcessHeap(), 0, sizeof(EdgeTableEntry) * total )))
return 0;
nb_points = REGION_CreateEdgeTable( Count, nbpolygons, Pts, &ET, pETEs, &SLLBlock, clip_rect );
if ((obj = alloc_region( nb_points / 2 )))
{
scan_convert( obj, &ET, mode, clip_rect );
if (!(hrgn = alloc_gdi_handle( obj, OBJ_REGION, &region_funcs ))) if (!(hrgn = alloc_gdi_handle( obj, OBJ_REGION, &region_funcs )))
free_region( obj ); free_region( obj );
}
done:
REGION_FreeStorage(SLLBlock.next); REGION_FreeStorage(SLLBlock.next);
HeapFree( GetProcessHeap(), 0, pETEs ); HeapFree( GetProcessHeap(), 0, pETEs );
return hrgn; return hrgn;