gdi32: Exponentially grow successive point buffers.
Huw Davies
huw at codeweavers.com
Tue Aug 16 09:09:30 CDT 2016
Signed-off-by: Huw Davies <huw at codeweavers.com>
---
dlls/gdi32/region.c | 34 ++++++++++++++++++----------------
1 file changed, 18 insertions(+), 16 deletions(-)
diff --git a/dlls/gdi32/region.c b/dlls/gdi32/region.c
index a4cf733..e9bed18 100644
--- a/dlls/gdi32/region.c
+++ b/dlls/gdi32/region.c
@@ -173,31 +173,28 @@ static inline BOOL is_in_rect( const RECT *rect, int x, int y )
}
/*
- * number of points to buffer before sending them off
- * to scanlines() : Must be an even number
- */
-#define NUMPTSTOBUFFER 200
-
-/*
* used to allocate buffers for points and link
* the buffers together
*/
struct point_block
{
- POINT pts[NUMPTSTOBUFFER];
- int count;
+ int count, size;
struct point_block *next;
+ POINT pts[1]; /* Variable sized array - must be last. */
};
static struct point_block *add_point( struct point_block *block, int x, int y )
{
- if (block->count == NUMPTSTOBUFFER)
+ if (block->count == block->size)
{
- struct point_block *new = HeapAlloc( GetProcessHeap(), 0, sizeof(*new) );
+ struct point_block *new;
+ int size = block->size * 2;
+ new = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( struct point_block, pts[size] ) );
if (!new) return NULL;
block->next = new;
new->count = 0;
+ new->size = size;
new->next = NULL;
block = new;
}
@@ -2676,6 +2673,9 @@ static WINEREGION *REGION_PtsToRegion( struct point_block *FirstPtBlock )
return reg;
}
+/* Number of points in the first point buffer. Must be an even number. */
+#define NUMPTSTOBUFFER 200
+
/***********************************************************************
* CreatePolyPolygonRgn (GDI32.@)
*/
@@ -2692,7 +2692,8 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count,
EdgeTableEntry *pETEs; /* EdgeTableEntries pool */
ScanLineListBlock SLLBlock; /* header for scanlinelist */
BOOL fixWAET = FALSE;
- struct point_block FirstPtBlock, *block; /* PtBlock buffers */
+ char first_blk_buf[FIELD_OFFSET( struct point_block, pts[NUMPTSTOBUFFER] )];
+ struct point_block *first_block = (struct point_block *)first_blk_buf, *block;
struct edge_table_entry *active, *next;
INT poly, total;
@@ -2721,9 +2722,10 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count,
REGION_CreateEdgeTable(Count, nbpolygons, Pts, &ET, pETEs, &SLLBlock);
list_init( &AET );
pSLL = ET.scanlines.next;
- block = &FirstPtBlock;
- FirstPtBlock.count = 0;
- FirstPtBlock.next = NULL;
+ block = first_block;
+ first_block->count = 0;
+ first_block->size = NUMPTSTOBUFFER;
+ first_block->next = NULL;
if (mode != WINDING) {
/*
@@ -2802,13 +2804,13 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count,
}
}
- if (!(obj = REGION_PtsToRegion( &FirstPtBlock ))) goto done;
+ if (!(obj = REGION_PtsToRegion( first_block ))) goto done;
if (!(hrgn = alloc_gdi_handle( obj, OBJ_REGION, ®ion_funcs )))
free_region( obj );
done:
REGION_FreeStorage(SLLBlock.next);
- free_point_blocks( FirstPtBlock.next );
+ free_point_blocks( first_block->next );
HeapFree( GetProcessHeap(), 0, pETEs );
return hrgn;
}
--
2.7.4
More information about the wine-patches
mailing list