Commit 6a9b775f authored by Alexandre Julliard's avatar Alexandre Julliard

gdi32: Add helper functions to manage blocks of points in CreatePolyPolygonRgn.

parent a34c6f43
...@@ -165,11 +165,39 @@ static inline BOOL is_in_rect( const RECT *rect, int x, int y ) ...@@ -165,11 +165,39 @@ static inline BOOL is_in_rect( const RECT *rect, int x, int y )
* the buffers together * the buffers together
*/ */
typedef struct _POINTBLOCK { struct point_block
{
POINT pts[NUMPTSTOBUFFER]; POINT pts[NUMPTSTOBUFFER];
struct _POINTBLOCK *next; int count;
} POINTBLOCK; struct point_block *next;
};
static struct point_block *add_point( struct point_block *block, int x, int y )
{
if (block->count == NUMPTSTOBUFFER)
{
struct point_block *new = HeapAlloc( GetProcessHeap(), 0, sizeof(*new) );
if (!new) return NULL;
block->next = new;
new->count = 0;
new->next = NULL;
block = new;
}
block->pts[block->count].x = x;
block->pts[block->count].y = y;
block->count++;
return block;
}
static void free_point_blocks( struct point_block *block )
{
while (block)
{
struct point_block *tmp = block->next;
HeapFree( GetProcessHeap(), 0, block );
block = tmp;
}
}
/* /*
...@@ -2665,33 +2693,30 @@ static void REGION_FreeStorage(ScanLineListBlock *pSLLBlock) ...@@ -2665,33 +2693,30 @@ static void REGION_FreeStorage(ScanLineListBlock *pSLLBlock)
* *
* Create an array of rectangles from a list of points. * Create an array of rectangles from a list of points.
*/ */
static BOOL REGION_PtsToRegion(int numFullPtBlocks, int iCurPtBlock, static BOOL REGION_PtsToRegion( struct point_block *FirstPtBlock, WINEREGION *reg )
POINTBLOCK *FirstPtBlock, WINEREGION *reg)
{ {
RECT *rects; RECT *rects;
POINT *pts; POINT *pts;
POINTBLOCK *CurPtBlock; struct point_block *pb;
int i; int i;
RECT *extents; RECT *extents;
INT numRects; INT numRects;
extents = &reg->extents; extents = &reg->extents;
numRects = ((numFullPtBlocks * NUMPTSTOBUFFER) + iCurPtBlock) >> 1; for (pb = FirstPtBlock, numRects = 0; pb; pb = pb->next) numRects += pb->count;
if (!init_region( reg, numRects )) return FALSE; if (!init_region( reg, numRects )) return FALSE;
reg->size = numRects; reg->size = numRects;
CurPtBlock = FirstPtBlock;
rects = reg->rects - 1; rects = reg->rects - 1;
numRects = 0; numRects = 0;
extents->left = LARGE_COORDINATE, extents->right = SMALL_COORDINATE; extents->left = LARGE_COORDINATE, extents->right = SMALL_COORDINATE;
for ( ; numFullPtBlocks >= 0; numFullPtBlocks--) { for (pb = FirstPtBlock; pb; pb = pb->next)
{
/* the loop uses 2 points per iteration */ /* the loop uses 2 points per iteration */
i = NUMPTSTOBUFFER >> 1; i = pb->count / 2;
if (!numFullPtBlocks) for (pts = pb->pts; i--; pts += 2) {
i = iCurPtBlock >> 1;
for (pts = CurPtBlock->pts; i--; pts += 2) {
if (pts->x == pts[1].x) if (pts->x == pts[1].x)
continue; continue;
if (numRects && pts->x == rects->left && pts->y == rects->bottom && if (numRects && pts->x == rects->left && pts->y == rects->bottom &&
...@@ -2710,7 +2735,6 @@ static BOOL REGION_PtsToRegion(int numFullPtBlocks, int iCurPtBlock, ...@@ -2710,7 +2735,6 @@ static BOOL REGION_PtsToRegion(int numFullPtBlocks, int iCurPtBlock,
if (rects->right > extents->right) if (rects->right > extents->right)
extents->right = rects->right; extents->right = rects->right;
} }
CurPtBlock = CurPtBlock->next;
} }
if (numRects) { if (numRects) {
...@@ -2737,19 +2761,15 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count, ...@@ -2737,19 +2761,15 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count,
WINEREGION *obj; WINEREGION *obj;
EdgeTableEntry *pAET; /* Active Edge Table */ EdgeTableEntry *pAET; /* Active Edge Table */
INT y; /* current scanline */ INT y; /* current scanline */
int iPts = 0; /* number of pts in buffer */
EdgeTableEntry *pWETE; /* Winding Edge Table Entry*/ EdgeTableEntry *pWETE; /* Winding Edge Table Entry*/
ScanLineList *pSLL; /* current scanLineList */ ScanLineList *pSLL; /* current scanLineList */
POINT *pts; /* output buffer */
EdgeTableEntry *pPrevAET; /* ptr to previous AET */ EdgeTableEntry *pPrevAET; /* ptr to previous AET */
EdgeTable ET; /* header node for ET */ EdgeTable ET; /* header node for ET */
EdgeTableEntry AET; /* header node for AET */ EdgeTableEntry AET; /* header node 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;
POINTBLOCK FirstPtBlock, *curPtBlock; /* PtBlock buffers */ struct point_block FirstPtBlock, *block; /* PtBlock buffers */
POINTBLOCK *tmpPtBlock;
int numFullPtBlocks = 0;
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);
...@@ -2774,10 +2794,11 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count, ...@@ -2774,10 +2794,11 @@ 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;
pts = FirstPtBlock.pts;
REGION_CreateETandAET(Count, nbpolygons, Pts, &ET, &AET, pETEs, &SLLBlock); REGION_CreateETandAET(Count, nbpolygons, Pts, &ET, &AET, pETEs, &SLLBlock);
pSLL = ET.scanlines.next; pSLL = ET.scanlines.next;
curPtBlock = &FirstPtBlock; block = &FirstPtBlock;
FirstPtBlock.count = 0;
FirstPtBlock.next = NULL;
if (mode != WINDING) { if (mode != WINDING) {
/* /*
...@@ -2799,21 +2820,8 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count, ...@@ -2799,21 +2820,8 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count,
* for each active edge * for each active edge
*/ */
while (pAET) { while (pAET) {
pts->x = pAET->bres.minor_axis, pts->y = y; block = add_point( block, pAET->bres.minor_axis, y );
pts++, iPts++; if (!block) goto done;
/*
* send out the buffer
*/
if (iPts == NUMPTSTOBUFFER) {
tmpPtBlock = HeapAlloc( GetProcessHeap(), 0, sizeof(POINTBLOCK));
if(!tmpPtBlock) goto done;
curPtBlock->next = tmpPtBlock;
curPtBlock = tmpPtBlock;
pts = curPtBlock->pts;
numFullPtBlocks++;
iPts = 0;
}
EVALUATEEDGEEVENODD(pAET, pPrevAET, y); EVALUATEEDGEEVENODD(pAET, pPrevAET, y);
} }
REGION_InsertionSort(&AET); REGION_InsertionSort(&AET);
...@@ -2846,22 +2854,8 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count, ...@@ -2846,22 +2854,8 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count,
* are in the Winding active edge table. * are in the Winding active edge table.
*/ */
if (pWETE == pAET) { if (pWETE == pAET) {
pts->x = pAET->bres.minor_axis, pts->y = y; block = add_point( block, pAET->bres.minor_axis, y );
pts++, iPts++; if (!block) goto done;
/*
* send out the buffer
*/
if (iPts == NUMPTSTOBUFFER) {
tmpPtBlock = HeapAlloc( GetProcessHeap(), 0,
sizeof(POINTBLOCK) );
if(!tmpPtBlock) goto done;
curPtBlock->next = tmpPtBlock;
curPtBlock = tmpPtBlock;
pts = curPtBlock->pts;
numFullPtBlocks++;
iPts = 0;
}
pWETE = pWETE->nextWETE; pWETE = pWETE->nextWETE;
} }
EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET); EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET);
...@@ -2880,7 +2874,7 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count, ...@@ -2880,7 +2874,7 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count,
if (!(obj = HeapAlloc( GetProcessHeap(), 0, sizeof(*obj) ))) goto done; if (!(obj = HeapAlloc( GetProcessHeap(), 0, sizeof(*obj) ))) goto done;
if (!REGION_PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, obj)) if (!REGION_PtsToRegion(&FirstPtBlock, obj))
{ {
HeapFree( GetProcessHeap(), 0, obj ); HeapFree( GetProcessHeap(), 0, obj );
goto done; goto done;
...@@ -2893,11 +2887,7 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count, ...@@ -2893,11 +2887,7 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count,
done: done:
REGION_FreeStorage(SLLBlock.next); REGION_FreeStorage(SLLBlock.next);
for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) { free_point_blocks( FirstPtBlock.next );
tmpPtBlock = curPtBlock->next;
HeapFree( GetProcessHeap(), 0, curPtBlock );
curPtBlock = tmpPtBlock;
}
HeapFree( GetProcessHeap(), 0, pETEs ); HeapFree( GetProcessHeap(), 0, pETEs );
return hrgn; return hrgn;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment