[3/3] gdi32: improved PolyDraw in path-closed case [try3]

Evan Stade estade at gmail.com
Mon Jul 16 21:45:32 CDT 2007


Hi,

This is a rewrite of the "else" case mentioned in part 2 of this series.

 dlls/gdi32/painting.c |   90 ++++++++++++++++++++++++++++---------------------
 1 files changed, 52 insertions(+), 38 deletions(-)
-- 
Evan Stade
-------------- next part --------------
diff --git a/dlls/gdi32/painting.c b/dlls/gdi32/painting.c
index ed3f9b0..a79c10f 100644
--- a/dlls/gdi32/painting.c
+++ b/dlls/gdi32/painting.c
@@ -824,8 +824,8 @@ BOOL WINAPI PolyDraw(HDC hdc, const POIN
 {
     DC *dc;
     BOOL result = FALSE;
-    POINT lastmove;
-    unsigned int i;
+    POINT * line_pts = NULL, * bzr_pts = NULL;
+    INT i, num_pts, num_bzr_pts, space, size;
 
     dc = DC_GetDCUpdate( hdc );
     if(!dc) return FALSE;
@@ -835,51 +835,65 @@ BOOL WINAPI PolyDraw(HDC hdc, const POIN
     else if(dc->funcs->pPolyDraw)
         result = dc->funcs->pPolyDraw( dc->physDev, lppt, lpbTypes, cCount );
     else {
-    /* 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 )
-		goto end;
-	    else
-		i += 2;
-	}
+        space = cCount + 1 + 300; 
+        line_pts = HeapAlloc(GetProcessHeap(), 0, space * sizeof(POINT));
+        num_pts = 1;
+
+        line_pts[0].x = dc->CursPosX;
+        line_pts[0].y = dc->CursPosY;
+
+        for(i = 0; i < cCount; i++) {
+            switch(lpbTypes[i]) {
+                case PT_MOVETO:
+                    if(num_pts >= 2)
+                        Polyline(dc->hSelf, line_pts, num_pts);
+                    num_pts = 0;
+                    line_pts[num_pts++] = lppt[i];
+                    break;
+                case PT_LINETO:
+                case (PT_LINETO | PT_CLOSEFIGURE):
+                    line_pts[num_pts++] = lppt[i];
+                    break;
+                case PT_BEZIERTO:
+                    if(lpbTypes[i+1] != PT_BEZIERTO ||
+                    (lpbTypes[i+2] & ~PT_CLOSEFIGURE) != PT_BEZIERTO)
+                        goto end;
+                    else {
+                        bzr_pts = GDI_Bezier(&lppt[i - 1], 4, &num_bzr_pts);
+
+                        size = num_pts + (cCount - i) + num_bzr_pts;
+                        if(space < size){
+                            space = size * 2;
+                            line_pts = HeapReAlloc(GetProcessHeap(), 0, line_pts,
+                                space * sizeof(POINT));
+                        }
+                        memcpy(&line_pts[num_pts], &bzr_pts[1],
+                            (num_bzr_pts - 1) * sizeof(POINT));
+                        num_pts += num_bzr_pts - 1;
+                        HeapFree(GetProcessHeap(), 0, bzr_pts);
+                        i += 2;
+                    }
+                    break;
+                default:
+                    ERR("Got path flag %d\n", (INT)lpbTypes[i]);
+                    goto end;
+            }
 
-    /* if no moveto occurs, we will close the figure here */
-    lastmove.x = dc->CursPosX;
-    lastmove.y = dc->CursPosY;
+            if(lpbTypes[i] & PT_CLOSEFIGURE)
+                line_pts[num_pts++] = line_pts[0];
+        }
 
-    /* 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
-	    goto end;
+        if(num_pts >= 2)
+            Polyline(dc->hSelf, line_pts, num_pts);
 
-	if( lpbTypes[i] & PT_CLOSEFIGURE )
-	{
-		LineTo( hdc, lastmove.x, lastmove.y );
-	}
+        MoveToEx(dc->hSelf, line_pts[num_pts - 1].x, line_pts[num_pts - 1].y, NULL);
     }
 
     result = TRUE;
-    }
 
 end:
     GDI_ReleaseObj( hdc );
+    HeapFree(GetProcessHeap(), 0, line_pts);
     return result;
 }
 
-- 
1.4.1


More information about the wine-patches mailing list