gdi32: Reduce the number of memory allocations required for gdi paths.

Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Huw Davies 2016-07-14 14:28:14 +01:00 committed by Alexandre Julliard
parent 54ec86021a
commit da8834609a
1 changed files with 41 additions and 21 deletions

View File

@ -89,6 +89,8 @@ struct gdi_path
int allocated; int allocated;
BOOL newStroke; BOOL newStroke;
POINT pos; /* current cursor position */ POINT pos; /* current cursor position */
POINT points_buf[NUM_ENTRIES_INITIAL];
BYTE flags_buf[NUM_ENTRIES_INITIAL];
}; };
struct path_physdev struct path_physdev
@ -104,8 +106,8 @@ static inline struct path_physdev *get_path_physdev( PHYSDEV dev )
void free_gdi_path( struct gdi_path *path ) void free_gdi_path( struct gdi_path *path )
{ {
HeapFree( GetProcessHeap(), 0, path->points ); if (path->points != path->points_buf)
HeapFree( GetProcessHeap(), 0, path->flags ); HeapFree( GetProcessHeap(), 0, path->points );
HeapFree( GetProcessHeap(), 0, path ); HeapFree( GetProcessHeap(), 0, path );
} }
@ -119,13 +121,22 @@ static struct gdi_path *alloc_gdi_path( int count )
return NULL; return NULL;
} }
count = max( NUM_ENTRIES_INITIAL, count ); count = max( NUM_ENTRIES_INITIAL, count );
path->points = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*path->points) ); if (count > NUM_ENTRIES_INITIAL)
path->flags = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*path->flags) );
if (!path->points || !path->flags)
{ {
free_gdi_path( path ); path->points = HeapAlloc( GetProcessHeap(), 0,
SetLastError( ERROR_NOT_ENOUGH_MEMORY ); count * (sizeof(path->points[0]) + sizeof(path->flags[0])) );
return NULL; if (!path->points)
{
HeapFree( GetProcessHeap(), 0, path );
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return NULL;
}
path->flags = (BYTE *)(path->points + count);
}
else
{
path->points = path->points_buf;
path->flags = path->flags_buf;
} }
path->count = 0; path->count = 0;
path->allocated = count; path->allocated = count;
@ -179,30 +190,39 @@ static inline INT int_from_fixed(FIXED f)
* been allocated; allocates larger arrays and copies the existing entries * been allocated; allocates larger arrays and copies the existing entries
* to those arrays, if necessary. Returns TRUE if successful, else FALSE. * to those arrays, if necessary. Returns TRUE if successful, else FALSE.
*/ */
static BOOL PATH_ReserveEntries(struct gdi_path *pPath, INT count) static BOOL PATH_ReserveEntries(struct gdi_path *path, INT count)
{ {
POINT *pPointsNew; POINT *pts_new;
BYTE *pFlagsNew; int size;
assert(count>=0); assert(count>=0);
/* Do we have to allocate more memory? */ /* Do we have to allocate more memory? */
if(count > pPath->allocated) if (count > path->allocated)
{ {
/* Find number of entries to allocate. We let the size of the array /* Find number of entries to allocate. We let the size of the array
* grow exponentially, since that will guarantee linear time * grow exponentially, since that will guarantee linear time
* complexity. */ * complexity. */
count = max( pPath->allocated * 2, count ); count = max( path->allocated * 2, count );
size = count * (sizeof(path->points[0]) + sizeof(path->flags[0]));
pPointsNew = HeapReAlloc( GetProcessHeap(), 0, pPath->points, count * sizeof(POINT) ); if (path->points == path->points_buf)
if (!pPointsNew) return FALSE; {
pPath->points = pPointsNew; pts_new = HeapAlloc( GetProcessHeap(), 0, size );
if (!pts_new) return FALSE;
memcpy( pts_new, path->points, path->count * sizeof(path->points[0]) );
memcpy( pts_new + count, path->flags, path->count * sizeof(path->flags[0]) );
}
else
{
pts_new = HeapReAlloc( GetProcessHeap(), 0, path->points, size );
if (!pts_new) return FALSE;
memmove( pts_new + count, pts_new + path->allocated, path->count * sizeof(path->flags[0]) );
}
pFlagsNew = HeapReAlloc( GetProcessHeap(), 0, pPath->flags, count * sizeof(BYTE) ); path->points = pts_new;
if (!pFlagsNew) return FALSE; path->flags = (BYTE *)(pts_new + count);
pPath->flags = pFlagsNew; path->allocated = count;
pPath->allocated = count;
} }
return TRUE; return TRUE;
} }