gdi32: PolyDraw while no path is open

Evan Stade estade at gmail.com
Tue Jun 26 22:05:09 CDT 2007


Hi,

This patch depends on the previous 3 patches I sent today.  It fixes
PolyDraw to work properly on DCs without an open path.  Most notably
it draws the lines/beziers as a Polyline, so that line joins work
properly.  It shares some code with StrokePath, but is less
restrictive on the types of points that it finds.  Also it now
properly updates the cursor position.

Along with the last patch I sent, this breaks up PolyDraw into
separate logic for the path open case and the path closed case.

Changelog:
* improved PolyDraw when used on a DC with no open path

 dlls/gdi32/painting.c |  142 ++++++++++++++++++++++++++++++++-----------------
 1 files changed, 94 insertions(+), 48 deletions(-)

-- 
Evan Stade
-------------- next part --------------
diff --git a/dlls/gdi32/painting.c b/dlls/gdi32/painting.c
index 923bd35..dffede0 100644
--- a/dlls/gdi32/painting.c
+++ b/dlls/gdi32/painting.c
@@ -34,7 +34,7 @@ #include "winerror.h"
 #include "gdi_private.h"
 #include "wine/debug.h"
 
-WINE_DEFAULT_DEBUG_CHANNEL(gdi);
+WINE_DEFAULT_DEBUG_CHANNEL(paint);
 
 
 /***********************************************************************
@@ -825,7 +825,11 @@ BOOL WINAPI PolyDraw(HDC hdc, const POIN
     DC *dc;
     BOOL result;
     POINT lastmove;
-    unsigned int i;
+    POINT *pBzrPts, *pLinePts;
+    unsigned int i, nLinePts;
+    INT nMinAlloc, nAlloc, nBzrPts;
+    BOOL ret;
+
 
     dc = DC_GetDCUpdate( hdc );
     if(!dc) return FALSE;
@@ -838,17 +842,7 @@ BOOL WINAPI PolyDraw(HDC hdc, const POIN
     }
     GDI_ReleaseObj( hdc );
 
-    /* check for each bezierto if there are two more points */
-    for( i = 0; i < cCount; i++ )
-	if( lpbTypes[i] != PT_MOVETO &&
-	    lpbTypes[i] & PT_BEZIERTO )
-	{
-	    if( cCount < i+3 )
-		return FALSE;
-	    else
-		i += 2;
-	}
-
+    /* Path open case */
     if( PATH_IsPathOpen( dc->path ) )
     {
         for( i = dc->path.numEntriesUsed-1; i >= 0; i-- ){
@@ -861,45 +855,97 @@ BOOL WINAPI PolyDraw(HDC hdc, const POIN
             lastmove.x = 0;
             lastmove.y = 0;
         }
-    }
-    else{
-        /* if no moveto occurs, we will close the figure here */
-        lastmove.x = dc->CursPosX;
-        lastmove.y = dc->CursPosY;
-    }
 
-    /* now let's draw */
-    for( i = 0; i < cCount; i++ )
-    {
-	if( lpbTypes[i] == PT_MOVETO )
-	{
-	    MoveToEx( hdc, lppt[i].x, lppt[i].y, NULL );
-	    lastmove.x = dc->CursPosX;
-	    lastmove.y = dc->CursPosY;
-	}
-	else if( lpbTypes[i] & PT_LINETO )
-	    LineTo( hdc, lppt[i].x, lppt[i].y );
-	else if( lpbTypes[i] & PT_BEZIERTO )
-	{
-	    PolyBezierTo( hdc, &lppt[i], 3 );
-	    i += 2;
-	}
-	else
-	    return FALSE;
-
-	if( lpbTypes[i] & PT_CLOSEFIGURE )
-	{
-	    if( PATH_IsPathOpen( dc->path ) ){
-            /* CloseFigure in a PolyDraw acts like a "CloseFigureTo" might act */
-            CloseFigure( hdc );
-            MoveToEx( hdc, lastmove.x, lastmove.y, NULL );
+        for( i = 0; i < cCount; i++ )
+        {
+            if( lpbTypes[i] == PT_MOVETO )
+            {
+                MoveToEx( hdc, lppt[i].x, lppt[i].y, NULL );
+                lastmove.x = dc->CursPosX;
+                lastmove.y = dc->CursPosY;
+            }
+            else if( lpbTypes[i] & PT_LINETO )
+                LineTo( hdc, lppt[i].x, lppt[i].y );
+            else if( lpbTypes[i] & PT_BEZIERTO )
+            {
+                PolyBezierTo( hdc, &lppt[i], 3 );
+                i += 2;
+            }
+            else
+                return FALSE;
+
+            if( lpbTypes[i] & PT_CLOSEFIGURE )
+            {
+                /* CloseFigure in a PolyDraw acts like a "CloseFigureTo" might act */
+                CloseFigure( hdc );
+                MoveToEx( hdc, lastmove.x, lastmove.y, NULL );
+            }
         }
-	    else
-		LineTo( hdc, lastmove.x, lastmove.y );
-	}
+
+        return TRUE;
     }
 
-    return TRUE;
+    /* Path not open case */
+    nAlloc = cCount + 1 + 300; 
+    pLinePts = HeapAlloc(GetProcessHeap(), 0, nAlloc * sizeof(POINT));
+    nLinePts = 1;
+    /* this might be overwritten if the first point is a moveto point */
+    pLinePts[0].x = dc->CursPosX;
+    pLinePts[0].y = dc->CursPosY;
+
+    for(i = 0; i < cCount; i++) {
+        switch(lpbTypes[i]) {
+            case PT_MOVETO:
+                if(nLinePts >= 2)
+                    Polyline(dc->hSelf, pLinePts, nLinePts);
+                nLinePts = 0;
+                pLinePts[nLinePts++] = lppt[i];
+                break;
+        case PT_LINETO:
+        case (PT_LINETO | PT_CLOSEFIGURE):
+            pLinePts[nLinePts++] = lppt[i];
+            break;
+        case PT_BEZIERTO:
+            if(lpbTypes[i+1] != PT_BEZIERTO ||
+            (lpbTypes[i+2] & ~PT_CLOSEFIGURE) != PT_BEZIERTO) {
+                ERR("points didn't contain 3 successive PT_BEZIERTOs\n");
+            ret = FALSE;
+            goto end;
+            } else {
+                pBzrPts = GDI_Bezier(&lppt[i-1], 4, &nBzrPts);
+
+                nMinAlloc = nLinePts + (cCount - i) + nBzrPts;
+                if(nAlloc < nMinAlloc){
+                    nAlloc = nMinAlloc * 2;
+                    pLinePts = HeapReAlloc(GetProcessHeap(), 0, pLinePts,
+                        nAlloc * sizeof(POINT));
+                }
+                memcpy(&pLinePts[nLinePts], &pBzrPts[1],
+                    (nBzrPts - 1) * sizeof(POINT));
+                nLinePts += nBzrPts - 1;
+                HeapFree(GetProcessHeap(), 0, pBzrPts);
+                i += 2;
+            }
+            break;
+        default:
+            ERR("Got path flag %d\n", (INT)lpbTypes[i]);
+            ret = FALSE;
+            goto end;
+        }
+
+        if(lpbTypes[i] & PT_CLOSEFIGURE)
+            pLinePts[nLinePts++] = pLinePts[0];
+        }
+
+    if(nLinePts >= 2)
+        Polyline(dc->hSelf, pLinePts, nLinePts);
+
+    MoveToEx(dc->hSelf, pLinePts[nLinePts-1].x, pLinePts[nLinePts-1].y, NULL);
+
+    ret = TRUE;
+end:
+    HeapFree(GetProcessHeap(), 0, pLinePts);
+    return ret;
 }
 
 
-- 
1.4.1


More information about the wine-patches mailing list