[2/2] gdi32: fixed PolyDraw [try2]

Evan Stade estade at gmail.com
Wed Jun 27 17:51:51 CDT 2007


Hi,

[try2] This fixes the problems that the last patch tested.  This patch
is more extensive than the one I submitted yesterday because the test
suite is now more extensive.  Thus it fixes more problems.

Basically this divides the logic of PolyDraw into separate cases for
when it's called with an open path and when it's called with a closed
path.  The closed-path case mirrors path-stroking (PATH_StrokePath in
path.c).  The open-path case is similar to the old PolyDraw, with some
logical changes (for example, the way type equality is tested).

Changelog
* fixed PolyDraw
* removed 5 todo_wines from path test

 dlls/gdi32/painting.c   |  165 +++++++++++++++++++++++++++++++++++------------
 dlls/gdi32/tests/path.c |   10 +--
 2 files changed, 127 insertions(+), 48 deletions(-)

-- 
Evan Stade
-------------- next part --------------
diff --git a/dlls/gdi32/painting.c b/dlls/gdi32/painting.c
index 1b30d6d..a1b51c0 100644
--- a/dlls/gdi32/painting.c
+++ b/dlls/gdi32/painting.c
@@ -823,9 +823,9 @@ BOOL WINAPI PolyDraw(HDC hdc, const POIN
                        DWORD cCount)
 {
     DC *dc;
-    BOOL result;
-    POINT lastmove;
-    unsigned int i;
+    BOOL result, reset_pos = FALSE, ret;
+    POINT lastmove, *pBzrPts, *pLinePts, orig_pos = {0, 0};
+    INT i, nLinePts, nMinAlloc, nAlloc, nBzrPts;
 
     dc = DC_GetDCUpdate( hdc );
     if(!dc) return FALSE;
@@ -838,50 +838,129 @@ 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;
-	}
-
-    /* if no moveto occurs, we will close the figure here */
-    lastmove.x = dc->CursPosX;
-    lastmove.y = dc->CursPosY;
+    orig_pos.x = dc->CursPosX;
+    orig_pos.y = dc->CursPosY;
 
-    /* now let's draw */
-    for( i = 0; i < cCount; i++ )
+    /* Path open case */
+    if( PATH_IsPathOpen( dc->path ) )
     {
-	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( hdc );
-	    else
-		LineTo( hdc, lastmove.x, lastmove.y );
-	}
+        for( i = dc->path.numEntriesUsed-1; i >= 0; i-- ){
+            if(dc->path.pFlags[i] == PT_MOVETO){
+                lastmove = dc->path.pPoints[i];
+                break;
+            }
+        }
+        if(i < 0){
+            lastmove.x = dc->CursPosX;
+            lastmove.y = dc->CursPosY;
+            MoveToEx( hdc, dc->CursPosX, dc->CursPosY, NULL);
+        }
+
+        for( i = 0; i < cCount; i++ )
+        {
+            if( (lpbTypes[i] & PT_MOVETO ) == 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 ) == PT_LINETO)
+                LineTo( hdc, lppt[i].x, lppt[i].y );
+            else if( (lpbTypes[i] & PT_BEZIERTO ) == PT_BEZIERTO)
+            {
+                if(!((i + 2 < cCount) &&
+                    ((lpbTypes[i + 1] & ~PT_CLOSEFIGURE) & PT_BEZIERTO )
+                    && ((lpbTypes[i + 2] & ~PT_CLOSEFIGURE) & PT_BEZIERTO ))){
+                    /* if we encounter a bad number of bezier points we stop
+                        drawing and reset the cursor position to what it was at
+                        the start of the PolyDraw */
+                    MoveToEx( hdc, orig_pos.x, orig_pos.y, NULL);
+                    return FALSE;
+                }
+
+                PolyBezierTo( hdc, &lppt[i], 3 );
+                i += 2;
+            }
+            else{
+                MoveToEx( hdc, orig_pos.x, orig_pos.y, NULL);
+                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 );
+            }
+        }
+
+        if(reset_pos){
+            MoveToEx( hdc, orig_pos.x, orig_pos.y, NULL );
+         }
+
+        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) {
+                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;
 }
 
 
diff --git a/dlls/gdi32/tests/path.c b/dlls/gdi32/tests/path.c
index ebbb73a..f9d6bb9 100644
--- a/dlls/gdi32/tests/path.c
+++ b/dlls/gdi32/tests/path.c
@@ -295,7 +295,7 @@ static const path_test_t polydraw_path[]
     {300, 300, 6, 0, 0}, /*0*/
     {150, 200, 2, 0, 0}, /*1*/
     {200, 150, 3, 0, 0}, /*2*/
-    {300, 300, 6, 0, 1}, /*3*/
+    {300, 300, 6, 0, 0}, /*3*/
     {300, 300, 2, 0, 0}, /*4*/
     {400, 300, 2, 0, 0}, /*5*/
     {400, 350, 2, 0, 0}, /*6*/
@@ -304,9 +304,9 @@ static const path_test_t polydraw_path[]
     {400, 250, 2, 0, 0}, /*9*/
     {500, 300, 2, 0, 0}, /*10*/
     {500, 350, 2, 0, 0}, /*11*/
-    {350, 400, 6, 0, 1}, /*12*/
-    {600, 200, 2, 0, 1}, /*13*/
-    {500, 150, 2, 0, 1}, /*14*/
+    {350, 400, 6, 0, 0}, /*12*/
+    {600, 200, 2, 0, 0}, /*13*/
+    {500, 150, 2, 0, 0}, /*14*/
     {500, 350, 6, 0, 0}, /*15*/
     {500, 150, 2, 0, 0}, /*16*/
     {100, 200, 2, 0, 0}, /*17*/
@@ -355,7 +355,7 @@ static void test_polydraw(void)
     ok(retb == FALSE, "Expected %d, got %d\n", FALSE, retb);
 
     EndPath(hdc);
-    ok_path(hdc, "polydraw_path", polydraw_path, sizeof(polydraw_path)/sizeof(path_test_t), 1);
+    ok_path(hdc, "polydraw_path", polydraw_path, sizeof(polydraw_path)/sizeof(path_test_t), 0);
 done:
     ReleaseDC(0, hdc);
 }
-- 
1.4.1


More information about the wine-patches mailing list