Alexandre Julliard : gdi32: Only store the path in the DC when it's closed.

Alexandre Julliard julliard at winehq.org
Wed Nov 23 13:40:06 CST 2011


Module: wine
Branch: master
Commit: 2201d08834f282e83791e93af980dc482f1b1b76
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=2201d08834f282e83791e93af980dc482f1b1b76

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed Nov 23 13:24:12 2011 +0100

gdi32: Only store the path in the DC when it's closed.

Open paths are stored only in the path physdev.

---

 dlls/gdi32/gdi_private.h |    1 +
 dlls/gdi32/path.c        |   93 +++++++++++++++++++++++++++------------------
 2 files changed, 57 insertions(+), 37 deletions(-)

diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index 70f2e4b..db53163 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -150,6 +150,7 @@ typedef struct tagDC
 } DC;
 
   /* DC flags */
+#define DC_PATH_OPEN     0x0001   /* DC path is open (only set on saved DCs) */
 #define DC_BOUNDS_ENABLE 0x0008   /* Bounding rectangle tracking is enabled */
 
 /* Certain functions will do no further processing if the driver returns this.
diff --git a/dlls/gdi32/path.c b/dlls/gdi32/path.c
index 715932c..c9b7262 100644
--- a/dlls/gdi32/path.c
+++ b/dlls/gdi32/path.c
@@ -108,11 +108,21 @@ static inline struct path_physdev *get_path_physdev( PHYSDEV dev )
     return (struct path_physdev *)dev;
 }
 
-static inline void pop_path_driver( DC *dc )
+static inline void pop_path_driver( DC *dc, struct path_physdev *physdev )
 {
-    PHYSDEV dev = pop_dc_driver( &dc->physDev );
-    assert( dev->funcs == &path_driver );
-    HeapFree( GetProcessHeap(), 0, dev );
+    PHYSDEV *dev = &dc->physDev;
+    while (*dev != &physdev->dev) dev = &(*dev)->next;
+    *dev = physdev->dev.next;
+    HeapFree( GetProcessHeap(), 0, physdev );
+}
+
+static inline struct path_physdev *find_path_physdev( DC *dc )
+{
+    PHYSDEV dev;
+
+    for (dev = dc->physDev; dev->funcs != &null_driver; dev = dev->next)
+        if (dev->funcs == &path_driver) return get_path_physdev( dev );
+    return NULL;
 }
 
 void free_gdi_path( struct gdi_path *path )
@@ -614,44 +624,39 @@ BOOL WINAPI CloseFigure(HDC hdc)
 /***********************************************************************
  *           GetPath    (GDI32.@)
  */
-INT WINAPI GetPath(HDC hdc, LPPOINT pPoints, LPBYTE pTypes,
-   INT nSize)
+INT WINAPI GetPath(HDC hdc, LPPOINT pPoints, LPBYTE pTypes, INT nSize)
 {
    INT ret = -1;
-   GdiPath *pPath;
    DC *dc = get_dc_ptr( hdc );
 
    if(!dc) return -1;
 
-   pPath = dc->path;
-
-   /* Check that path is closed */
-   if(!pPath || pPath->state != PATH_Closed)
+   if (!dc->path)
    {
       SetLastError(ERROR_CAN_NOT_COMPLETE);
       goto done;
    }
 
    if(nSize==0)
-      ret = pPath->numEntriesUsed;
-   else if(nSize<pPath->numEntriesUsed)
+      ret = dc->path->numEntriesUsed;
+   else if(nSize<dc->path->numEntriesUsed)
    {
       SetLastError(ERROR_INVALID_PARAMETER);
       goto done;
    }
    else
    {
-      memcpy(pPoints, pPath->pPoints, sizeof(POINT)*pPath->numEntriesUsed);
-      memcpy(pTypes, pPath->pFlags, sizeof(BYTE)*pPath->numEntriesUsed);
+      memcpy(pPoints, dc->path->pPoints, sizeof(POINT)*dc->path->numEntriesUsed);
+      memcpy(pTypes, dc->path->pFlags, sizeof(BYTE)*dc->path->numEntriesUsed);
 
       /* Convert the points to logical coordinates */
-      if(!DPtoLP(hdc, pPoints, pPath->numEntriesUsed))
+      if(!DPtoLP(hdc, pPoints, dc->path->numEntriesUsed))
       {
 	 /* FIXME: Is this the correct value? */
          SetLastError(ERROR_CAN_NOT_COMPLETE);
 	goto done;
       }
-     else ret = pPath->numEntriesUsed;
+     else ret = dc->path->numEntriesUsed;
    }
  done:
    release_dc_ptr( dc );
@@ -676,8 +681,7 @@ HRGN WINAPI PathToRegion(HDC hdc)
    /* Get pointer to path */
    if(!dc) return 0;
 
-   /* Check that path is closed */
-   if (!dc->path || dc->path->state != PATH_Closed) SetLastError(ERROR_CAN_NOT_COMPLETE);
+   if (!dc->path) SetLastError(ERROR_CAN_NOT_COMPLETE);
    else
    {
        if ((hrgnRval = PATH_PathToRegion(dc->path, GetPolyFillMode(hdc))))
@@ -811,12 +815,12 @@ static BOOL pathdrv_BeginPath( PHYSDEV dev )
  */
 static BOOL pathdrv_AbortPath( PHYSDEV dev )
 {
+    struct path_physdev *physdev = get_path_physdev( dev );
     DC *dc = get_dc_ptr( dev->hdc );
 
     if (!dc) return FALSE;
-    free_gdi_path( dc->path );
-    dc->path = NULL;
-    pop_path_driver( dc );
+    free_gdi_path( physdev->path );
+    pop_path_driver( dc, physdev );
     release_dc_ptr( dc );
     return TRUE;
 }
@@ -827,11 +831,13 @@ static BOOL pathdrv_AbortPath( PHYSDEV dev )
  */
 static BOOL pathdrv_EndPath( PHYSDEV dev )
 {
+    struct path_physdev *physdev = get_path_physdev( dev );
     DC *dc = get_dc_ptr( dev->hdc );
 
     if (!dc) return FALSE;
+    dc->path = physdev->path;
     dc->path->state = PATH_Closed;
-    pop_path_driver( dc );
+    pop_path_driver( dc, physdev );
     release_dc_ptr( dc );
     return TRUE;
 }
@@ -866,30 +872,43 @@ static BOOL pathdrv_DeleteDC( PHYSDEV dev )
 
 BOOL PATH_SavePath( DC *dst, DC *src )
 {
+    struct path_physdev *physdev;
+
     if (src->path)
     {
         if (!(dst->path = copy_gdi_path( src->path ))) return FALSE;
     }
+    else if ((physdev = find_path_physdev( src )))
+    {
+        if (!(dst->path = copy_gdi_path( physdev->path ))) return FALSE;
+        dst->flags |= DC_PATH_OPEN;
+    }
     else dst->path = NULL;
     return TRUE;
 }
 
 BOOL PATH_RestorePath( DC *dst, DC *src )
 {
-    struct path_physdev *physdev;
+    struct path_physdev *physdev = find_path_physdev( dst );
 
-    if (src->path && src->path->state == PATH_Open)
+    if (src->path && (src->flags & DC_PATH_OPEN))
     {
-        if (!dst->path || dst->path->state != PATH_Open)
+        if (!physdev)
         {
             if (!path_driver.pCreateDC( &dst->physDev, NULL, NULL, NULL, NULL )) return FALSE;
+            physdev = get_path_physdev( dst->physDev );
         }
-        physdev = get_path_physdev( dst->physDev );
-        assert( physdev->dev.funcs == &path_driver );
+        else free_gdi_path( physdev->path );
+
         physdev->path = src->path;
+        src->flags &= ~DC_PATH_OPEN;
+        src->path = NULL;
+    }
+    else if (physdev)
+    {
+        free_gdi_path( physdev->path );
+        pop_path_driver( dst, physdev );
     }
-    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;
@@ -2106,7 +2125,7 @@ BOOL nulldrv_BeginPath( PHYSDEV dev )
     physdev = get_path_physdev( dc->physDev );
     physdev->path = path;
     if (dc->path) free_gdi_path( dc->path );
-    dc->path = path;
+    dc->path = NULL;
     return TRUE;
 }
 
@@ -2137,7 +2156,7 @@ BOOL nulldrv_SelectClipPath( PHYSDEV dev, INT mode )
     HRGN hrgn;
     DC *dc = get_nulldrv_dc( dev );
 
-    if (!dc->path || dc->path->state != PATH_Closed)
+    if (!dc->path)
     {
         SetLastError( ERROR_CAN_NOT_COMPLETE );
         return FALSE;
@@ -2158,7 +2177,7 @@ BOOL nulldrv_FillPath( PHYSDEV dev )
 {
     DC *dc = get_nulldrv_dc( dev );
 
-    if (!dc->path || dc->path->state != PATH_Closed)
+    if (!dc->path)
     {
         SetLastError( ERROR_CAN_NOT_COMPLETE );
         return FALSE;
@@ -2174,7 +2193,7 @@ BOOL nulldrv_StrokeAndFillPath( PHYSDEV dev )
 {
     DC *dc = get_nulldrv_dc( dev );
 
-    if (!dc->path || dc->path->state != PATH_Closed)
+    if (!dc->path)
     {
         SetLastError( ERROR_CAN_NOT_COMPLETE );
         return FALSE;
@@ -2190,7 +2209,7 @@ BOOL nulldrv_StrokePath( PHYSDEV dev )
 {
     DC *dc = get_nulldrv_dc( dev );
 
-    if (!dc->path || dc->path->state != PATH_Closed)
+    if (!dc->path)
     {
         SetLastError( ERROR_CAN_NOT_COMPLETE );
         return FALSE;
@@ -2206,7 +2225,7 @@ BOOL nulldrv_FlattenPath( PHYSDEV dev )
     DC *dc = get_nulldrv_dc( dev );
     struct gdi_path *path;
 
-    if (!dc->path || dc->path->state != PATH_Closed)
+    if (!dc->path)
     {
         SetLastError( ERROR_CAN_NOT_COMPLETE );
         return FALSE;
@@ -2222,7 +2241,7 @@ BOOL nulldrv_WidenPath( PHYSDEV dev )
     DC *dc = get_nulldrv_dc( dev );
     struct gdi_path *path;
 
-    if (!dc->path || dc->path->state != PATH_Closed)
+    if (!dc->path)
     {
         SetLastError( ERROR_CAN_NOT_COMPLETE );
         return FALSE;




More information about the wine-cvs mailing list