gdi32: Store a pointer to the path in the DC and make the path structure opaque.
This commit is contained in:
parent
ddc9860a42
commit
a214a3c3da
|
@ -110,6 +110,7 @@ DC *alloc_dc_ptr( WORD magic )
|
|||
dc->hDevice = 0;
|
||||
dc->hPalette = GetStockObject( DEFAULT_PALETTE );
|
||||
dc->gdiFont = 0;
|
||||
dc->path = NULL;
|
||||
dc->font_code_page = CP_ACP;
|
||||
dc->ROPmode = R2_COPYPEN;
|
||||
dc->polyFillMode = ALTERNATE;
|
||||
|
@ -146,7 +147,6 @@ DC *alloc_dc_ptr( WORD magic )
|
|||
dc->BoundsRect.top = 0;
|
||||
dc->BoundsRect.right = 0;
|
||||
dc->BoundsRect.bottom = 0;
|
||||
PATH_InitGdiPath(&dc->path);
|
||||
|
||||
if (!(dc->hSelf = alloc_gdi_handle( &dc->header, magic, &dc_funcs )))
|
||||
{
|
||||
|
@ -174,7 +174,7 @@ static void free_dc_state( DC *dc )
|
|||
if (dc->hMetaRgn) DeleteObject( dc->hMetaRgn );
|
||||
if (dc->hMetaClipRgn) DeleteObject( dc->hMetaClipRgn );
|
||||
if (dc->hVisRgn) DeleteObject( dc->hVisRgn );
|
||||
PATH_DestroyGdiPath( &dc->path );
|
||||
if (dc->path) free_gdi_path( dc->path );
|
||||
HeapFree( GetProcessHeap(), 0, dc );
|
||||
}
|
||||
|
||||
|
|
|
@ -72,27 +72,6 @@ typedef struct tagGDIOBJHDR
|
|||
struct hdc_list *hdcs;
|
||||
} GDIOBJHDR;
|
||||
|
||||
/* It should not be necessary to access the contents of the GdiPath
|
||||
* structure directly; if you find that the exported functions don't
|
||||
* allow you to do what you want, then please place a new exported
|
||||
* function that does this job in path.c.
|
||||
*/
|
||||
typedef enum tagGdiPathState
|
||||
{
|
||||
PATH_Null,
|
||||
PATH_Open,
|
||||
PATH_Closed
|
||||
} GdiPathState;
|
||||
|
||||
typedef struct gdi_path
|
||||
{
|
||||
GdiPathState state;
|
||||
POINT *pPoints;
|
||||
BYTE *pFlags;
|
||||
int numEntriesUsed, numEntriesAllocated;
|
||||
BOOL newStroke;
|
||||
} GdiPath;
|
||||
|
||||
typedef struct tagGdiFont GdiFont;
|
||||
|
||||
typedef struct tagDC
|
||||
|
@ -137,7 +116,7 @@ typedef struct tagDC
|
|||
HPALETTE hPalette;
|
||||
|
||||
GdiFont *gdiFont;
|
||||
GdiPath path;
|
||||
struct gdi_path *path;
|
||||
|
||||
UINT font_code_page;
|
||||
WORD ROPmode;
|
||||
|
@ -320,8 +299,7 @@ extern METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mr, LPCVOID filename, BOO
|
|||
|
||||
/* path.c */
|
||||
|
||||
extern void PATH_InitGdiPath(GdiPath *pPath) DECLSPEC_HIDDEN;
|
||||
extern void PATH_DestroyGdiPath(GdiPath *pPath) DECLSPEC_HIDDEN;
|
||||
extern void free_gdi_path( struct gdi_path *path ) DECLSPEC_HIDDEN;
|
||||
extern BOOL PATH_SavePath( DC *dst, DC *src ) DECLSPEC_HIDDEN;
|
||||
extern BOOL PATH_RestorePath( DC *dst, DC *src ) DECLSPEC_HIDDEN;
|
||||
|
||||
|
|
|
@ -81,11 +81,26 @@ typedef struct tagFLOAT_POINT
|
|||
double x, y;
|
||||
} FLOAT_POINT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PATH_Null,
|
||||
PATH_Open,
|
||||
PATH_Closed
|
||||
} GdiPathState;
|
||||
|
||||
typedef struct gdi_path
|
||||
{
|
||||
GdiPathState state;
|
||||
POINT *pPoints;
|
||||
BYTE *pFlags;
|
||||
int numEntriesUsed, numEntriesAllocated;
|
||||
BOOL newStroke;
|
||||
} GdiPath;
|
||||
|
||||
struct path_physdev
|
||||
{
|
||||
struct gdi_physdev dev;
|
||||
GdiPath *path;
|
||||
struct gdi_path *path;
|
||||
};
|
||||
|
||||
static inline struct path_physdev *get_path_physdev( PHYSDEV dev )
|
||||
|
@ -100,7 +115,7 @@ static inline void pop_path_driver( DC *dc )
|
|||
HeapFree( GetProcessHeap(), 0, dev );
|
||||
}
|
||||
|
||||
static void free_gdi_path( struct gdi_path *path )
|
||||
void free_gdi_path( struct gdi_path *path )
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, path->pPoints );
|
||||
HeapFree( GetProcessHeap(), 0, path->pFlags );
|
||||
|
@ -131,6 +146,31 @@ static struct gdi_path *alloc_gdi_path(void)
|
|||
return path;
|
||||
}
|
||||
|
||||
static struct gdi_path *copy_gdi_path( const struct gdi_path *src_path )
|
||||
{
|
||||
struct gdi_path *path = HeapAlloc( GetProcessHeap(), 0, sizeof(*path) );
|
||||
|
||||
if (!path)
|
||||
{
|
||||
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
||||
return NULL;
|
||||
}
|
||||
path->state = src_path->state;
|
||||
path->numEntriesUsed = path->numEntriesAllocated = src_path->numEntriesUsed;
|
||||
path->newStroke = src_path->newStroke;
|
||||
path->pPoints = HeapAlloc( GetProcessHeap(), 0, path->numEntriesUsed * sizeof(*path->pPoints) );
|
||||
path->pFlags = HeapAlloc( GetProcessHeap(), 0, path->numEntriesUsed * sizeof(*path->pFlags) );
|
||||
if (!path->pPoints || !path->pFlags)
|
||||
{
|
||||
free_gdi_path( path );
|
||||
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
||||
return NULL;
|
||||
}
|
||||
memcpy( path->pPoints, src_path->pPoints, path->numEntriesUsed * sizeof(*path->pPoints) );
|
||||
memcpy( path->pFlags, src_path->pFlags, path->numEntriesUsed * sizeof(*path->pFlags) );
|
||||
return path;
|
||||
}
|
||||
|
||||
/* Performs a world-to-viewport transformation on the specified point (which
|
||||
* is in floating point format).
|
||||
*/
|
||||
|
@ -156,16 +196,6 @@ static inline INT int_from_fixed(FIXED f)
|
|||
}
|
||||
|
||||
|
||||
/* PATH_EmptyPath
|
||||
*
|
||||
* Removes all entries from the path and sets the path state to PATH_Null.
|
||||
*/
|
||||
static void PATH_EmptyPath(GdiPath *pPath)
|
||||
{
|
||||
pPath->state=PATH_Null;
|
||||
pPath->numEntriesUsed=0;
|
||||
}
|
||||
|
||||
/* PATH_ReserveEntries
|
||||
*
|
||||
* Ensures that at least "numEntries" entries (for points and flags) have
|
||||
|
@ -262,35 +292,6 @@ static BOOL start_new_stroke( struct path_physdev *physdev )
|
|||
return add_log_points( physdev, &pos, 1, PT_MOVETO ) != NULL;
|
||||
}
|
||||
|
||||
/* PATH_AssignGdiPath
|
||||
*
|
||||
* Copies the GdiPath structure "pPathSrc" to "pPathDest". A deep copy is
|
||||
* performed, i.e. the contents of the pPoints and pFlags arrays are copied,
|
||||
* not just the pointers. Since this means that the arrays in pPathDest may
|
||||
* need to be resized, pPathDest should have been initialized using
|
||||
* PATH_InitGdiPath (in C++, this function would be an assignment operator,
|
||||
* not a copy constructor).
|
||||
* Returns TRUE if successful, else FALSE.
|
||||
*/
|
||||
static BOOL PATH_AssignGdiPath(GdiPath *pPathDest, const GdiPath *pPathSrc)
|
||||
{
|
||||
/* Make sure destination arrays are big enough */
|
||||
if(!PATH_ReserveEntries(pPathDest, pPathSrc->numEntriesUsed))
|
||||
return FALSE;
|
||||
|
||||
/* Perform the copy operation */
|
||||
memcpy(pPathDest->pPoints, pPathSrc->pPoints,
|
||||
sizeof(POINT)*pPathSrc->numEntriesUsed);
|
||||
memcpy(pPathDest->pFlags, pPathSrc->pFlags,
|
||||
sizeof(BYTE)*pPathSrc->numEntriesUsed);
|
||||
|
||||
pPathDest->state=pPathSrc->state;
|
||||
pPathDest->numEntriesUsed=pPathSrc->numEntriesUsed;
|
||||
pPathDest->newStroke=pPathSrc->newStroke;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* PATH_CheckCorners
|
||||
*
|
||||
* Helper function for RoundRect() and Rectangle()
|
||||
|
@ -622,10 +623,10 @@ INT WINAPI GetPath(HDC hdc, LPPOINT pPoints, LPBYTE pTypes,
|
|||
|
||||
if(!dc) return -1;
|
||||
|
||||
pPath = &dc->path;
|
||||
pPath = dc->path;
|
||||
|
||||
/* Check that path is closed */
|
||||
if(pPath->state!=PATH_Closed)
|
||||
if(!pPath || pPath->state != PATH_Closed)
|
||||
{
|
||||
SetLastError(ERROR_CAN_NOT_COMPLETE);
|
||||
goto done;
|
||||
|
@ -669,22 +670,22 @@ INT WINAPI GetPath(HDC hdc, LPPOINT pPoints, LPBYTE pTypes,
|
|||
*/
|
||||
HRGN WINAPI PathToRegion(HDC hdc)
|
||||
{
|
||||
GdiPath *pPath;
|
||||
HRGN hrgnRval = 0;
|
||||
DC *dc = get_dc_ptr( hdc );
|
||||
|
||||
/* Get pointer to path */
|
||||
if(!dc) return 0;
|
||||
|
||||
pPath = &dc->path;
|
||||
|
||||
/* Check that path is closed */
|
||||
if(pPath->state!=PATH_Closed) SetLastError(ERROR_CAN_NOT_COMPLETE);
|
||||
if (!dc->path || dc->path->state != PATH_Closed) SetLastError(ERROR_CAN_NOT_COMPLETE);
|
||||
else
|
||||
{
|
||||
if ((hrgnRval = PATH_PathToRegion(dc->path, GetPolyFillMode(hdc))))
|
||||
{
|
||||
/* FIXME: Should we empty the path even if conversion failed? */
|
||||
hrgnRval = PATH_PathToRegion(pPath, GetPolyFillMode(hdc));
|
||||
if (hrgnRval) PATH_EmptyPath(pPath);
|
||||
free_gdi_path( dc->path );
|
||||
dc->path = NULL;
|
||||
}
|
||||
}
|
||||
release_dc_ptr( dc );
|
||||
return hrgnRval;
|
||||
|
@ -813,7 +814,8 @@ static BOOL pathdrv_AbortPath( PHYSDEV dev )
|
|||
DC *dc = get_dc_ptr( dev->hdc );
|
||||
|
||||
if (!dc) return FALSE;
|
||||
PATH_EmptyPath( &dc->path );
|
||||
free_gdi_path( dc->path );
|
||||
dc->path = NULL;
|
||||
pop_path_driver( dc );
|
||||
release_dc_ptr( dc );
|
||||
return TRUE;
|
||||
|
@ -828,7 +830,7 @@ static BOOL pathdrv_EndPath( PHYSDEV dev )
|
|||
DC *dc = get_dc_ptr( dev->hdc );
|
||||
|
||||
if (!dc) return FALSE;
|
||||
dc->path.state = PATH_Closed;
|
||||
dc->path->state = PATH_Closed;
|
||||
pop_path_driver( dc );
|
||||
release_dc_ptr( dc );
|
||||
return TRUE;
|
||||
|
@ -846,7 +848,6 @@ static BOOL pathdrv_CreateDC( PHYSDEV *dev, LPCWSTR driver, LPCWSTR device,
|
|||
|
||||
if (!physdev) return FALSE;
|
||||
dc = get_dc_ptr( (*dev)->hdc );
|
||||
physdev->path = &dc->path;
|
||||
push_dc_driver( dev, &physdev->dev, &path_driver );
|
||||
release_dc_ptr( dc );
|
||||
return TRUE;
|
||||
|
@ -863,56 +864,36 @@ static BOOL pathdrv_DeleteDC( PHYSDEV dev )
|
|||
}
|
||||
|
||||
|
||||
/* PATH_InitGdiPath
|
||||
*
|
||||
* Initializes the GdiPath structure.
|
||||
*/
|
||||
void PATH_InitGdiPath(GdiPath *pPath)
|
||||
{
|
||||
assert(pPath!=NULL);
|
||||
|
||||
pPath->state=PATH_Null;
|
||||
pPath->pPoints=NULL;
|
||||
pPath->pFlags=NULL;
|
||||
pPath->numEntriesUsed=0;
|
||||
pPath->numEntriesAllocated=0;
|
||||
}
|
||||
|
||||
/* PATH_DestroyGdiPath
|
||||
*
|
||||
* Destroys a GdiPath structure (frees the memory in the arrays).
|
||||
*/
|
||||
void PATH_DestroyGdiPath(GdiPath *pPath)
|
||||
{
|
||||
assert(pPath!=NULL);
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, pPath->pPoints );
|
||||
HeapFree( GetProcessHeap(), 0, pPath->pFlags );
|
||||
}
|
||||
|
||||
BOOL PATH_SavePath( DC *dst, DC *src )
|
||||
{
|
||||
PATH_InitGdiPath( &dst->path );
|
||||
return PATH_AssignGdiPath( &dst->path, &src->path );
|
||||
if (src->path)
|
||||
{
|
||||
if (!(dst->path = copy_gdi_path( src->path ))) return FALSE;
|
||||
}
|
||||
else dst->path = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL PATH_RestorePath( DC *dst, DC *src )
|
||||
{
|
||||
BOOL ret;
|
||||
struct path_physdev *physdev;
|
||||
|
||||
if (src->path.state == PATH_Open && dst->path.state != PATH_Open)
|
||||
if (src->path && src->path->state == PATH_Open)
|
||||
{
|
||||
if (!dst->path || dst->path->state != PATH_Open)
|
||||
{
|
||||
if (!path_driver.pCreateDC( &dst->physDev, NULL, NULL, NULL, NULL )) return FALSE;
|
||||
ret = PATH_AssignGdiPath( &dst->path, &src->path );
|
||||
if (!ret) pop_path_driver( dst );
|
||||
}
|
||||
else if (src->path.state != PATH_Open && dst->path.state == PATH_Open)
|
||||
{
|
||||
ret = PATH_AssignGdiPath( &dst->path, &src->path );
|
||||
if (ret) pop_path_driver( dst );
|
||||
physdev = get_path_physdev( dst->physDev );
|
||||
assert( physdev->dev.funcs == &path_driver );
|
||||
physdev->path = src->path;
|
||||
}
|
||||
else ret = PATH_AssignGdiPath( &dst->path, &src->path );
|
||||
return ret;
|
||||
else if (dst->path && dst->path->state == PATH_Open) pop_path_driver( dst );
|
||||
|
||||
if (dst->path) free_gdi_path( dst->path );
|
||||
dst->path = src->path;
|
||||
src->path = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1797,7 +1778,7 @@ static struct gdi_path *PATH_WidenPath(DC *dc)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (!(flat_path = PATH_FlattenPath( &dc->path ))) return NULL;
|
||||
if (!(flat_path = PATH_FlattenPath( dc->path ))) return NULL;
|
||||
|
||||
penWidthIn = penWidth / 2;
|
||||
penWidthOut = penWidth / 2;
|
||||
|
@ -2113,11 +2094,19 @@ BOOL WINAPI WidenPath(HDC hdc)
|
|||
BOOL nulldrv_BeginPath( PHYSDEV dev )
|
||||
{
|
||||
DC *dc = get_nulldrv_dc( dev );
|
||||
struct path_physdev *physdev;
|
||||
struct gdi_path *path = alloc_gdi_path();
|
||||
|
||||
if (!path_driver.pCreateDC( &dc->physDev, NULL, NULL, NULL, NULL )) return FALSE;
|
||||
PATH_EmptyPath(&dc->path);
|
||||
dc->path.newStroke = TRUE;
|
||||
dc->path.state = PATH_Open;
|
||||
if (!path) return FALSE;
|
||||
if (!path_driver.pCreateDC( &dc->physDev, NULL, NULL, NULL, NULL ))
|
||||
{
|
||||
free_gdi_path( path );
|
||||
return FALSE;
|
||||
}
|
||||
physdev = get_path_physdev( dc->physDev );
|
||||
physdev->path = path;
|
||||
if (dc->path) free_gdi_path( dc->path );
|
||||
dc->path = path;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -2131,7 +2120,8 @@ BOOL nulldrv_AbortPath( PHYSDEV dev )
|
|||
{
|
||||
DC *dc = get_nulldrv_dc( dev );
|
||||
|
||||
PATH_EmptyPath( &dc->path );
|
||||
if (dc->path) free_gdi_path( dc->path );
|
||||
dc->path = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -2147,14 +2137,18 @@ BOOL nulldrv_SelectClipPath( PHYSDEV dev, INT mode )
|
|||
HRGN hrgn;
|
||||
DC *dc = get_nulldrv_dc( dev );
|
||||
|
||||
if (dc->path.state != PATH_Closed)
|
||||
if (!dc->path || dc->path->state != PATH_Closed)
|
||||
{
|
||||
SetLastError( ERROR_CAN_NOT_COMPLETE );
|
||||
return FALSE;
|
||||
}
|
||||
if (!(hrgn = PATH_PathToRegion( &dc->path, GetPolyFillMode(dev->hdc)))) return FALSE;
|
||||
if (!(hrgn = PATH_PathToRegion( dc->path, GetPolyFillMode(dev->hdc)))) return FALSE;
|
||||
ret = ExtSelectClipRgn( dev->hdc, hrgn, mode ) != ERROR;
|
||||
if (ret) PATH_EmptyPath( &dc->path );
|
||||
if (ret)
|
||||
{
|
||||
free_gdi_path( dc->path );
|
||||
dc->path = NULL;
|
||||
}
|
||||
/* FIXME: Should this function delete the path even if it failed? */
|
||||
DeleteObject( hrgn );
|
||||
return ret;
|
||||
|
@ -2164,14 +2158,15 @@ BOOL nulldrv_FillPath( PHYSDEV dev )
|
|||
{
|
||||
DC *dc = get_nulldrv_dc( dev );
|
||||
|
||||
if (dc->path.state != PATH_Closed)
|
||||
if (!dc->path || dc->path->state != PATH_Closed)
|
||||
{
|
||||
SetLastError( ERROR_CAN_NOT_COMPLETE );
|
||||
return FALSE;
|
||||
}
|
||||
if (!PATH_FillPath( dev->hdc, &dc->path )) return FALSE;
|
||||
if (!PATH_FillPath( dev->hdc, dc->path )) return FALSE;
|
||||
/* FIXME: Should the path be emptied even if conversion failed? */
|
||||
PATH_EmptyPath( &dc->path );
|
||||
free_gdi_path( dc->path );
|
||||
dc->path = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -2179,14 +2174,15 @@ BOOL nulldrv_StrokeAndFillPath( PHYSDEV dev )
|
|||
{
|
||||
DC *dc = get_nulldrv_dc( dev );
|
||||
|
||||
if (dc->path.state != PATH_Closed)
|
||||
if (!dc->path || dc->path->state != PATH_Closed)
|
||||
{
|
||||
SetLastError( ERROR_CAN_NOT_COMPLETE );
|
||||
return FALSE;
|
||||
}
|
||||
if (!PATH_FillPath( dev->hdc, &dc->path )) return FALSE;
|
||||
if (!PATH_StrokePath( dev->hdc, &dc->path )) return FALSE;
|
||||
PATH_EmptyPath( &dc->path );
|
||||
if (!PATH_FillPath( dev->hdc, dc->path )) return FALSE;
|
||||
if (!PATH_StrokePath( dev->hdc, dc->path )) return FALSE;
|
||||
free_gdi_path( dc->path );
|
||||
dc->path = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -2194,13 +2190,14 @@ BOOL nulldrv_StrokePath( PHYSDEV dev )
|
|||
{
|
||||
DC *dc = get_nulldrv_dc( dev );
|
||||
|
||||
if (dc->path.state != PATH_Closed)
|
||||
if (!dc->path || dc->path->state != PATH_Closed)
|
||||
{
|
||||
SetLastError( ERROR_CAN_NOT_COMPLETE );
|
||||
return FALSE;
|
||||
}
|
||||
if (!PATH_StrokePath( dev->hdc, &dc->path )) return FALSE;
|
||||
PATH_EmptyPath( &dc->path );
|
||||
if (!PATH_StrokePath( dev->hdc, dc->path )) return FALSE;
|
||||
free_gdi_path( dc->path );
|
||||
dc->path = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -2209,14 +2206,14 @@ BOOL nulldrv_FlattenPath( PHYSDEV dev )
|
|||
DC *dc = get_nulldrv_dc( dev );
|
||||
struct gdi_path *path;
|
||||
|
||||
if (dc->path.state != PATH_Closed)
|
||||
if (!dc->path || dc->path->state != PATH_Closed)
|
||||
{
|
||||
SetLastError( ERROR_CAN_NOT_COMPLETE );
|
||||
return FALSE;
|
||||
}
|
||||
if (!(path = PATH_FlattenPath( &dc->path ))) return FALSE;
|
||||
PATH_AssignGdiPath( &dc->path, path );
|
||||
free_gdi_path( path );
|
||||
if (!(path = PATH_FlattenPath( dc->path ))) return FALSE;
|
||||
free_gdi_path( dc->path );
|
||||
dc->path = path;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -2225,14 +2222,14 @@ BOOL nulldrv_WidenPath( PHYSDEV dev )
|
|||
DC *dc = get_nulldrv_dc( dev );
|
||||
struct gdi_path *path;
|
||||
|
||||
if (dc->path.state != PATH_Closed)
|
||||
if (!dc->path || dc->path->state != PATH_Closed)
|
||||
{
|
||||
SetLastError( ERROR_CAN_NOT_COMPLETE );
|
||||
return FALSE;
|
||||
}
|
||||
if (!(path = PATH_WidenPath( dc ))) return FALSE;
|
||||
PATH_AssignGdiPath( &dc->path, path );
|
||||
free_gdi_path( path );
|
||||
free_gdi_path( dc->path );
|
||||
dc->path = path;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue