gdi32: Store a pointer to the path in the DC and make the path structure opaque.
diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c
index 4eb8997..b357cee 100644
--- a/dlls/gdi32/dc.c
+++ b/dlls/gdi32/dc.c
@@ -110,6 +110,7 @@
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->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 @@
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 );
}
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index 0868e14..70f2e4b 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -72,27 +72,6 @@
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 @@
HPALETTE hPalette;
GdiFont *gdiFont;
- GdiPath path;
+ struct gdi_path *path;
UINT font_code_page;
WORD ROPmode;
@@ -320,8 +299,7 @@
/* 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;
diff --git a/dlls/gdi32/path.c b/dlls/gdi32/path.c
index a8c9c89..715932c 100644
--- a/dlls/gdi32/path.c
+++ b/dlls/gdi32/path.c
@@ -81,11 +81,26 @@
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 @@
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 @@
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 @@
}
-/* 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 @@
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 @@
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 @@
*/
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
{
- /* FIXME: Should we empty the path even if conversion failed? */
- hrgnRval = PATH_PathToRegion(pPath, GetPolyFillMode(hdc));
- if (hrgnRval) PATH_EmptyPath(pPath);
+ if ((hrgnRval = PATH_PathToRegion(dc->path, GetPolyFillMode(hdc))))
+ {
+ /* FIXME: Should we empty the path even if conversion failed? */
+ free_gdi_path( dc->path );
+ dc->path = NULL;
+ }
}
release_dc_ptr( dc );
return hrgnRval;
@@ -813,7 +814,8 @@
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 @@
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 @@
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 @@
}
-/* 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 (!path_driver.pCreateDC( &dst->physDev, NULL, NULL, NULL, NULL )) return FALSE;
- ret = PATH_AssignGdiPath( &dst->path, &src->path );
- if (!ret) pop_path_driver( dst );
+ if (!dst->path || dst->path->state != PATH_Open)
+ {
+ if (!path_driver.pCreateDC( &dst->physDev, NULL, NULL, NULL, NULL )) return FALSE;
+ }
+ physdev = get_path_physdev( dst->physDev );
+ assert( physdev->dev.funcs == &path_driver );
+ physdev->path = src->path;
}
- 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 );
- }
- 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 @@
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 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 @@
{
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 @@
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 @@
{
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 @@
{
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 @@
{
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 @@
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 @@
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;
}